Merge lp:~javier.collado/utah/utah_client_common_docs into lp:utah
- utah_client_common_docs
- Merge into dev
Proposed by
Javier Collado
Status: | Merged |
---|---|
Approved by: | Javier Collado |
Approved revision: | 823 |
Merged at revision: | 824 |
Proposed branch: | lp:~javier.collado/utah/utah_client_common_docs |
Merge into: | lp:utah |
Diff against target: |
511 lines (+245/-63) 2 files modified
docs/source/reference.rst (+3/-0) utah/client/common.py (+242/-63) |
To merge this branch: | bzr merge lp:~javier.collado/utah/utah_client_common_docs |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Joe Talbott (community) | Approve | ||
UTAH Dev | Pending | ||
Review via email:
|
Commit message
Description of the change
This branch add some text to the documentation strings in utah.client.common
module.
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'docs/source/reference.rst' | |||
2 | --- docs/source/reference.rst 2012-12-12 20:58:59 +0000 | |||
3 | +++ docs/source/reference.rst 2013-02-27 09:07:24 +0000 | |||
4 | @@ -59,6 +59,9 @@ | |||
5 | 59 | 59 | ||
6 | 60 | .. automodule:: utah.client | 60 | .. automodule:: utah.client |
7 | 61 | 61 | ||
8 | 62 | ``utah.client.common`` | ||
9 | 63 | ---------------------- | ||
10 | 64 | |||
11 | 62 | .. automodule:: utah.client.common | 65 | .. automodule:: utah.client.common |
12 | 63 | :members: | 66 | :members: |
13 | 64 | 67 | ||
14 | 65 | 68 | ||
15 | === modified file 'utah/client/common.py' | |||
16 | --- utah/client/common.py 2013-02-15 08:55:48 +0000 | |||
17 | +++ utah/client/common.py 2013-02-27 09:07:24 +0000 | |||
18 | @@ -13,9 +13,7 @@ | |||
19 | 13 | # You should have received a copy of the GNU General Public License along | 13 | # You should have received a copy of the GNU General Public License along |
20 | 14 | # with this program. If not, see <http://www.gnu.org/licenses/>. | 14 | # with this program. If not, see <http://www.gnu.org/licenses/>. |
21 | 15 | 15 | ||
25 | 16 | """ | 16 | """UTAH client common classes and functions.""" |
23 | 17 | Common methods. | ||
24 | 18 | """ | ||
26 | 19 | 17 | ||
27 | 20 | import datetime | 18 | import datetime |
28 | 21 | import re | 19 | import re |
29 | @@ -75,16 +73,39 @@ | |||
30 | 75 | 73 | ||
31 | 76 | 74 | ||
32 | 77 | def do_nothing(_obj=None): | 75 | def do_nothing(_obj=None): |
37 | 78 | """ | 76 | """Placeholder for save_state_callbacks. |
38 | 79 | Do nothing method used a placeholder for save_state_callbacks. | 77 | |
39 | 80 | """ | 78 | .. seealso:: :class:`.TestSuite`, :class:`.TestCase` |
40 | 81 | pass | 79 | |
41 | 80 | """ | ||
42 | 82 | 81 | ||
43 | 83 | 82 | ||
44 | 84 | # Inspired by: | 83 | # Inspired by: |
45 | 85 | # http://stackoverflow.com/a/3326559 | 84 | # http://stackoverflow.com/a/3326559 |
46 | 86 | def run_cmd(command, cwd=None, timeout=0, cmd_type=CMD_TC_TEST, run_as=None, | 85 | def run_cmd(command, cwd=None, timeout=0, cmd_type=CMD_TC_TEST, run_as=None, |
47 | 87 | battery_measurements=False): | 86 | battery_measurements=False): |
48 | 87 | """Run command and return result using the client's format. | ||
49 | 88 | |||
50 | 89 | :param command: Command as it would be written in a console | ||
51 | 90 | :type command: str | ||
52 | 91 | :param cwd: Current working directory path | ||
53 | 92 | :type cwd: str | ||
54 | 93 | :param timeout: | ||
55 | 94 | Maximum amount of time in seconds to wait for the command to complete | ||
56 | 95 | :type timeout: int | ||
57 | 96 | :param cmd_type: Command type as displayed in the result object | ||
58 | 97 | :type cmd_type: str | ||
59 | 98 | :param run_as: Username to use to run the command | ||
60 | 99 | :type run_as: int | ||
61 | 100 | :param battery_measurements: | ||
62 | 101 | Flag to configure when to get battery related information | ||
63 | 102 | :type battery_measurements: bool | ||
64 | 103 | :returns: Command execution result | ||
65 | 104 | :rtype: dict | ||
66 | 105 | |||
67 | 106 | .. seealso:: :func:`make_result` | ||
68 | 107 | |||
69 | 108 | """ | ||
70 | 88 | 109 | ||
71 | 89 | if run_as is not None: | 110 | if run_as is not None: |
72 | 90 | # add -n so sudo will not prompt for a password on the tty | 111 | # add -n so sudo will not prompt for a password on the tty |
73 | @@ -172,6 +193,13 @@ | |||
74 | 172 | Make sure that byte strings are used only for ascii data and unicode | 193 | Make sure that byte strings are used only for ascii data and unicode |
75 | 173 | strings for strings using any other encoding. | 194 | strings for strings using any other encoding. |
76 | 174 | 195 | ||
77 | 196 | :param value: Data string that should be normalized | ||
78 | 197 | :type value: str | ||
79 | 198 | :param encoding: Encoding used to decode the given string | ||
80 | 199 | :type encoding: str | ||
81 | 200 | :returns: Data string reencoded using in ascii if possible | ||
82 | 201 | :rtype: str | ||
83 | 202 | |||
84 | 175 | """ | 203 | """ |
85 | 176 | unicode_value = value.decode(encoding) | 204 | unicode_value = value.decode(encoding) |
86 | 177 | try: | 205 | try: |
87 | @@ -185,10 +213,37 @@ | |||
88 | 185 | # TODO: it might make sense to have a result object that keeps track of | 213 | # TODO: it might make sense to have a result object that keeps track of |
89 | 186 | # test pass, fail, error and serializes it's data. | 214 | # test pass, fail, error and serializes it's data. |
90 | 187 | def make_result(command, retcode, stdout='', stderr='', start_time='', | 215 | def make_result(command, retcode, stdout='', stderr='', start_time='', |
92 | 188 | time_delta='', cmd_type=CMD_TC_TEST, user="unknown", | 216 | time_delta='', cmd_type=CMD_TC_TEST, user='unknown', |
93 | 189 | start_battery=None, end_battery=None): | 217 | start_battery=None, end_battery=None): |
96 | 190 | """ | 218 | """Make a result data structure. |
97 | 191 | Make a result dictionary. | 219 | |
98 | 220 | .. note:: | ||
99 | 221 | Battery information will only be included if some value is passed as | ||
100 | 222 | argument. | ||
101 | 223 | |||
102 | 224 | :param command: Command that was executed | ||
103 | 225 | :type command: str | ||
104 | 226 | :param retcode: Return code | ||
105 | 227 | :type retcode: int | ||
106 | 228 | :param stdout: Standard output | ||
107 | 229 | :type stdout: str | ||
108 | 230 | :param stderr: Standard error | ||
109 | 231 | :type stderr: str | ||
110 | 232 | :param start_time: Time in which command execution started | ||
111 | 233 | :type start_time: str | ||
112 | 234 | :param time_delta: Amount of time that the command took to complete | ||
113 | 235 | :type time_delta: str | ||
114 | 236 | :param cmd_type: Command type to be displayed in the report | ||
115 | 237 | :type cmd_type: str | ||
116 | 238 | :param user: User name the executed the command | ||
117 | 239 | :type user: str | ||
118 | 240 | :param start_battery: Battery information before running the command | ||
119 | 241 | :type start_battery: dict | ||
120 | 242 | :param end_battery: Battery information after running the command | ||
121 | 243 | :type end_battery: dict | ||
122 | 244 | :returns: Result data | ||
123 | 245 | :rtype: dict | ||
124 | 246 | |||
125 | 192 | """ | 247 | """ |
126 | 193 | res = { | 248 | res = { |
127 | 194 | 'command': command, | 249 | 'command': command, |
128 | @@ -212,6 +267,14 @@ | |||
129 | 212 | 267 | ||
130 | 213 | 268 | ||
131 | 214 | def get_process_children(pid): | 269 | def get_process_children(pid): |
132 | 270 | """Get the children processes of a given one. | ||
133 | 271 | |||
134 | 272 | :param pid: Process ID of the parent process | ||
135 | 273 | :type pid: int | ||
136 | 274 | :returns: Process ID for the childern processes | ||
137 | 275 | :rtype: list(int) | ||
138 | 276 | |||
139 | 277 | """ | ||
140 | 215 | p = subprocess.Popen('ps --no-headers -o pid --ppid %d' % pid, shell=True, | 278 | p = subprocess.Popen('ps --no-headers -o pid --ppid %d' % pid, shell=True, |
141 | 216 | stdout=subprocess.PIPE, stderr=subprocess.PIPE) | 279 | stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
142 | 217 | stdout, _stderr = p.communicate() | 280 | stdout, _stderr = p.communicate() |
143 | @@ -220,9 +283,18 @@ | |||
144 | 220 | 283 | ||
145 | 221 | 284 | ||
146 | 222 | def parse_yaml_file(filename): | 285 | def parse_yaml_file(filename): |
150 | 223 | """ | 286 | """Parse yaml file. |
151 | 224 | Parse yaml file and raise exception with error location | 287 | |
152 | 225 | in case of error | 288 | :param filename: Path to the file that should be read |
153 | 289 | :type filename: str | ||
154 | 290 | :returns: Parsed data | ||
155 | 291 | :rtype: object | ||
156 | 292 | :raises YAMLParsingError: | ||
157 | 293 | If there's a problem while parsing the file with the information about | ||
158 | 294 | where in the file the problem was detected. | ||
159 | 295 | |||
160 | 296 | .. seealso:: :func:`parse_control_file` | ||
161 | 297 | |||
162 | 226 | """ | 298 | """ |
163 | 227 | try: | 299 | try: |
164 | 228 | with open(filename, 'r') as fp: | 300 | with open(filename, 'r') as fp: |
165 | @@ -247,7 +319,16 @@ | |||
166 | 247 | # Validator that sets values to defaults as explained in: | 319 | # Validator that sets values to defaults as explained in: |
167 | 248 | # https://github.com/Julian/jsonschema/issues/4 | 320 | # https://github.com/Julian/jsonschema/issues/4 |
168 | 249 | class DefaultValidator(jsonschema.Validator): | 321 | class DefaultValidator(jsonschema.Validator): |
169 | 322 | |||
170 | 323 | """jsonschema validator that sets default values. | ||
171 | 324 | |||
172 | 325 | During the validation, if some field is missing in the data, it will be set | ||
173 | 326 | to the default value specified in the schema if defined. | ||
174 | 327 | |||
175 | 328 | """ | ||
176 | 329 | |||
177 | 250 | def validate_properties(self, properties, instance, schema): | 330 | def validate_properties(self, properties, instance, schema): |
178 | 331 | """Set missing properties to default value.""" | ||
179 | 251 | (super(DefaultValidator, self) | 332 | (super(DefaultValidator, self) |
180 | 252 | .validate_properties(properties, instance, schema)) | 333 | .validate_properties(properties, instance, schema)) |
181 | 253 | instance.update((k, v['default']) | 334 | instance.update((k, v['default']) |
182 | @@ -256,8 +337,19 @@ | |||
183 | 256 | 337 | ||
184 | 257 | 338 | ||
185 | 258 | def parse_control_file(filename, schema): | 339 | def parse_control_file(filename, schema): |
188 | 259 | """ | 340 | """Parse a control file and check against a jsonschema. |
189 | 260 | Parse a control file and check against the schema | 341 | |
190 | 342 | :param filename: Path to the yaml file to be parsed | ||
191 | 343 | :type filename: str | ||
192 | 344 | :param schema: jsonschema to validate data against | ||
193 | 345 | :type schema: dict | ||
194 | 346 | :returns: Parsed data | ||
195 | 347 | :rtype: object | ||
196 | 348 | :raises jsonschema.ValidationError: | ||
197 | 349 | If file contents doesn't follow the schema definitions | ||
198 | 350 | |||
199 | 351 | .. seealso:: :func:`parse_yaml_file`, :class:`DefaultValidator` | ||
200 | 352 | |||
201 | 261 | """ | 353 | """ |
202 | 262 | control_data = parse_yaml_file(filename) | 354 | control_data = parse_yaml_file(filename) |
203 | 263 | validator = DefaultValidator() | 355 | validator = DefaultValidator() |
204 | @@ -266,8 +358,17 @@ | |||
205 | 266 | 358 | ||
206 | 267 | 359 | ||
207 | 268 | def debug_print(data, force=False): | 360 | def debug_print(data, force=False): |
210 | 269 | """ | 361 | """Print debugging information according to ``CONFIG['DEBUG']`` value. |
211 | 270 | Print debugging information if CONFIG['DEBUG'] is defined and True | 362 | |
212 | 363 | Data will be printed with the ``DEBUG:`` string prepended to it. | ||
213 | 364 | |||
214 | 365 | :param data: Data to be printed | ||
215 | 366 | :type data: object | ||
216 | 367 | :param force: Print data regardless of the configuration | ||
217 | 368 | :type force: bool | ||
218 | 369 | :returns: Whether something was printed or not | ||
219 | 370 | :rtype: bool | ||
220 | 371 | |||
221 | 271 | """ | 372 | """ |
222 | 272 | try: | 373 | try: |
223 | 273 | debug = CONFIG['DEBUG'] | 374 | debug = CONFIG['DEBUG'] |
224 | @@ -284,8 +385,11 @@ | |||
225 | 284 | 385 | ||
226 | 285 | 386 | ||
227 | 286 | def raise_privileges(orig_privs): | 387 | def raise_privileges(orig_privs): |
230 | 287 | """ | 388 | """Raise privileges to original effective privileges. |
231 | 288 | Raise privileges to original effective privileges. | 389 | |
232 | 390 | :param orig_privs: Original privileges | ||
233 | 391 | :type orig_privs: dict | ||
234 | 392 | |||
235 | 289 | """ | 393 | """ |
236 | 290 | os.seteuid(orig_privs['euid']) | 394 | os.seteuid(orig_privs['euid']) |
237 | 291 | os.setegid(orig_privs['egid']) | 395 | os.setegid(orig_privs['egid']) |
238 | @@ -293,12 +397,18 @@ | |||
239 | 293 | 397 | ||
240 | 294 | 398 | ||
241 | 295 | def drop_privileges(user='nobody', group='nogroup', full=False): | 399 | def drop_privileges(user='nobody', group='nogroup', full=False): |
244 | 296 | """ | 400 | """Change user and/or group to decrease privileges. |
243 | 297 | Change user and/or group to decrease privileges. | ||
245 | 298 | 401 | ||
246 | 299 | Currently only drops effective privileges. | 402 | Currently only drops effective privileges. |
247 | 300 | 403 | ||
249 | 301 | Returns a dictionary of the original values. | 404 | :param user: User name to change to. |
250 | 405 | :type user: str | ||
251 | 406 | :param group: Group name to change to. | ||
252 | 407 | :type group: str | ||
253 | 408 | |||
254 | 409 | :returns: Original prrivileges | ||
255 | 410 | :rtype: dict | ||
256 | 411 | |||
257 | 302 | """ | 412 | """ |
258 | 303 | 413 | ||
259 | 304 | orig_privs = {} | 414 | orig_privs = {} |
260 | @@ -333,8 +443,13 @@ | |||
261 | 333 | 443 | ||
262 | 334 | 444 | ||
263 | 335 | def gather_artifacts(extras=None, excludes=None): | 445 | def gather_artifacts(extras=None, excludes=None): |
266 | 336 | """ | 446 | """Print files contents, so that it's included in the logs. |
267 | 337 | Include a set of useful artifacts (i.e. files) for the logs. | 447 | |
268 | 448 | :param extras: Path to files to be included in the artifacts | ||
269 | 449 | :type extras: list(str) | ||
270 | 450 | :param excludes: Path to files to be exluded from the artifacts | ||
271 | 451 | :type excludes: list(str) | ||
272 | 452 | |||
273 | 338 | """ | 453 | """ |
274 | 339 | if extras is None: | 454 | if extras is None: |
275 | 340 | extras = [] | 455 | extras = [] |
276 | @@ -366,12 +481,14 @@ | |||
277 | 366 | 481 | ||
278 | 367 | 482 | ||
279 | 368 | def get_media_info(): | 483 | def get_media_info(): |
286 | 369 | """ | 484 | """Get the contents of the media-info file if available. |
287 | 370 | Get the contents of the media-info file if available. | 485 | |
288 | 371 | 486 | :returns: | |
289 | 372 | NOTE: This is only a best-effort approach. | 487 | The contents of the media-info file or ``'unknown'`` if not available. |
290 | 373 | 488 | :rtype: str | |
291 | 374 | Returns the contents of the media-info file or None. | 489 | |
292 | 490 | .. note:: This is only a best-effort approach. | ||
293 | 491 | |||
294 | 375 | """ | 492 | """ |
295 | 376 | 493 | ||
296 | 377 | filename = '/var/log/installer/media-info' | 494 | filename = '/var/log/installer/media-info' |
297 | @@ -386,12 +503,13 @@ | |||
298 | 386 | 503 | ||
299 | 387 | 504 | ||
300 | 388 | def get_product_uuid(): | 505 | def get_product_uuid(): |
307 | 389 | """ | 506 | """Get the product_uuid of the machine under test. |
308 | 390 | Get the product_uuid of the machine under test. | 507 | |
309 | 391 | 508 | :returns: | |
310 | 392 | NOTE: This is only a best-effort approach. | 509 | The contents of the product_uuid file or ``None`` if not available. |
311 | 393 | 510 | ||
312 | 394 | Returns the contents of the product_uuid file or None. | 511 | .. note:: This is only a best-effort approach. |
313 | 512 | |||
314 | 395 | """ | 513 | """ |
315 | 396 | 514 | ||
316 | 397 | filename = '/sys/class/dmi/id/product_uuid' | 515 | filename = '/sys/class/dmi/id/product_uuid' |
317 | @@ -406,8 +524,13 @@ | |||
318 | 406 | 524 | ||
319 | 407 | 525 | ||
320 | 408 | def get_host_info(): | 526 | def get_host_info(): |
323 | 409 | """ | 527 | """Get host info, useful for debugging. |
324 | 410 | Get host info, useful for debugging. | 528 | |
325 | 529 | :returns: Host uname, media-info and product_uuid together | ||
326 | 530 | :rtype: dict | ||
327 | 531 | |||
328 | 532 | .. seealso:: :func:`get_media_info`, :func:`get_product_uuid` | ||
329 | 533 | |||
330 | 411 | """ | 534 | """ |
331 | 412 | 535 | ||
332 | 413 | retval = {} | 536 | retval = {} |
333 | @@ -421,10 +544,11 @@ | |||
334 | 421 | 544 | ||
335 | 422 | 545 | ||
336 | 423 | def get_arch(): | 546 | def get_arch(): |
341 | 424 | """ | 547 | """Get the host's architecture. |
342 | 425 | The host's architecture. | 548 | |
343 | 426 | 549 | :returns: The human readable architecture or ``'unknown'`` | |
344 | 427 | Returns the human readable architecture or 'unknown'. | 550 | :rtype: str |
345 | 551 | |||
346 | 428 | """ | 552 | """ |
347 | 429 | arches = { | 553 | arches = { |
348 | 430 | 'x86_64': 'amd64', | 554 | 'x86_64': 'amd64', |
349 | @@ -436,15 +560,20 @@ | |||
350 | 436 | 560 | ||
351 | 437 | 561 | ||
352 | 438 | def get_release(): | 562 | def get_release(): |
357 | 439 | """ | 563 | """Get the host's release name. |
358 | 440 | The host's release name (i.e. precise, quantal, etc.) | 564 | |
359 | 441 | """ | 565 | :returns: Release name (i.e. quantal, raring, etc.) |
360 | 442 | return platform.dist()[2] | 566 | :rtype: str |
361 | 567 | |||
362 | 568 | """ | ||
363 | 569 | return platform.linux_distribution()[2] | ||
364 | 443 | 570 | ||
365 | 444 | 571 | ||
366 | 445 | def get_api_config(): | 572 | def get_api_config(): |
369 | 446 | """ | 573 | """Parse the client configuration file for API configuration data. |
370 | 447 | Parse the client configuration file for API configuration data. | 574 | |
371 | 575 | :returns: The value for the ``API`` field in the client configuration file. | ||
372 | 576 | |||
373 | 448 | """ | 577 | """ |
374 | 449 | 578 | ||
375 | 450 | data = {} | 579 | data = {} |
376 | @@ -457,6 +586,14 @@ | |||
377 | 457 | 586 | ||
378 | 458 | 587 | ||
379 | 459 | def get_build_number(): | 588 | def get_build_number(): |
380 | 589 | """Get build number. | ||
381 | 590 | |||
382 | 591 | :returns: Build number as according to media-info or ``'?'`` if not found | ||
383 | 592 | :rtype: str | ||
384 | 593 | |||
385 | 594 | .. seealso:: :func:`get_host_info` | ||
386 | 595 | |||
387 | 596 | """ | ||
388 | 460 | host_info = get_host_info() | 597 | host_info = get_host_info() |
389 | 461 | pattern = re.compile('.*\(([0-9.]+)\)$') | 598 | pattern = re.compile('.*\(([0-9.]+)\)$') |
390 | 462 | match = pattern.match(host_info['media-info']) | 599 | match = pattern.match(host_info['media-info']) |
391 | @@ -469,8 +606,19 @@ | |||
392 | 469 | 606 | ||
393 | 470 | 607 | ||
394 | 471 | class VCSHandler(object): | 608 | class VCSHandler(object): |
397 | 472 | """ | 609 | |
398 | 473 | Base class for Version Ccontrol System support. | 610 | """Base class for Version Control System support. |
399 | 611 | |||
400 | 612 | :param repo: Repository location | ||
401 | 613 | :type repo: str | ||
402 | 614 | :param destination: | ||
403 | 615 | Local directory where the repository should be made available | ||
404 | 616 | :type destination: str | ||
405 | 617 | :param battery_measurements: | ||
406 | 618 | Whether battery information should be gathered when running any of the | ||
407 | 619 | VCS commands | ||
408 | 620 | :type battery_measurements: bool | ||
409 | 621 | |||
410 | 474 | """ | 622 | """ |
411 | 475 | 623 | ||
412 | 476 | def __init__(self, repo, destination='', battery_measurements=False): | 624 | def __init__(self, repo, destination='', battery_measurements=False): |
413 | @@ -479,8 +627,18 @@ | |||
414 | 479 | self.battery_measurements = battery_measurements | 627 | self.battery_measurements = battery_measurements |
415 | 480 | 628 | ||
416 | 481 | def get(self, directory=REPO_DEFAULT_DIR): | 629 | def get(self, directory=REPO_DEFAULT_DIR): |
419 | 482 | """ | 630 | """Execute VCS get command. |
420 | 483 | Method to retrieve a copy of the repository | 631 | |
421 | 632 | The get command will make a copy of a given repository to the directory | ||
422 | 633 | specified as destination. | ||
423 | 634 | |||
424 | 635 | :param directory: Working directory | ||
425 | 636 | :type directory: str | ||
426 | 637 | :returns: Get command execution result | ||
427 | 638 | :rtype: dict | ||
428 | 639 | |||
429 | 640 | .. seealso:: :func:`run_cmd` | ||
430 | 641 | |||
431 | 484 | """ | 642 | """ |
432 | 485 | return run_cmd(self.get_command, | 643 | return run_cmd(self.get_command, |
433 | 486 | cwd=directory, | 644 | cwd=directory, |
434 | @@ -488,8 +646,15 @@ | |||
435 | 488 | battery_measurements=self.battery_measurements) | 646 | battery_measurements=self.battery_measurements) |
436 | 489 | 647 | ||
437 | 490 | def revision(self, directory=REPO_DEFAULT_DIR): | 648 | def revision(self, directory=REPO_DEFAULT_DIR): |
440 | 491 | """ | 649 | """Execute revision command. |
441 | 492 | Return the revision identifier. | 650 | |
442 | 651 | :param directory: Working directory | ||
443 | 652 | :type directory: str | ||
444 | 653 | :returns: Revision command execution result. | ||
445 | 654 | :rtype: dict | ||
446 | 655 | |||
447 | 656 | .. seealso:: :func:`run_cmd`, :meth:`get_revision` | ||
448 | 657 | |||
449 | 493 | """ | 658 | """ |
450 | 494 | return run_cmd(self.rev_command, | 659 | return run_cmd(self.rev_command, |
451 | 495 | cwd=directory, | 660 | cwd=directory, |
452 | @@ -497,8 +662,18 @@ | |||
453 | 497 | battery_measurements=self.battery_measurements) | 662 | battery_measurements=self.battery_measurements) |
454 | 498 | 663 | ||
455 | 499 | def get_revision(self, directory=REPO_DEFAULT_DIR): | 664 | def get_revision(self, directory=REPO_DEFAULT_DIR): |
458 | 500 | """ | 665 | """Print revision information. |
459 | 501 | get the revision information | 666 | |
460 | 667 | This is a wrapper around :meth:`revision` to make sure that the command | ||
461 | 668 | returned a success code. | ||
462 | 669 | |||
463 | 670 | :param directory: Working directory | ||
464 | 671 | :type directory: str | ||
465 | 672 | :returns: Revision command returncode | ||
466 | 673 | :rtype: int | ||
467 | 674 | |||
468 | 675 | .. seealso:: :meth:`revision` | ||
469 | 676 | |||
470 | 502 | """ | 677 | """ |
471 | 503 | retval = None | 678 | retval = None |
472 | 504 | result = self.revision(directory=directory) | 679 | result = self.revision(directory=directory) |
473 | @@ -512,9 +687,8 @@ | |||
474 | 512 | 687 | ||
475 | 513 | 688 | ||
476 | 514 | class BzrHandler(VCSHandler): | 689 | class BzrHandler(VCSHandler): |
480 | 515 | """ | 690 | |
481 | 516 | bazaar handler. | 691 | """Bazaar VCS handler.""" |
479 | 517 | """ | ||
482 | 518 | 692 | ||
483 | 519 | def __init__(self, repo, branch=True, options="", destination="", | 693 | def __init__(self, repo, branch=True, options="", destination="", |
484 | 520 | **kwargs): | 694 | **kwargs): |
485 | @@ -540,9 +714,8 @@ | |||
486 | 540 | 714 | ||
487 | 541 | 715 | ||
488 | 542 | class GitHandler(VCSHandler): | 716 | class GitHandler(VCSHandler): |
492 | 543 | """ | 717 | |
493 | 544 | git handler. | 718 | """Git VCS handler.""" |
491 | 545 | """ | ||
494 | 546 | 719 | ||
495 | 547 | def __init__(self, repo, options="", destination="", **kwargs): | 720 | def __init__(self, repo, options="", destination="", **kwargs): |
496 | 548 | super(GitHandler, self).__init__(repo, destination, **kwargs) | 721 | super(GitHandler, self).__init__(repo, destination, **kwargs) |
497 | @@ -558,7 +731,13 @@ | |||
498 | 558 | 731 | ||
499 | 559 | 732 | ||
500 | 560 | class DevHandler(VCSHandler): | 733 | class DevHandler(VCSHandler): |
502 | 561 | """ Copy from a local directory for development. """ | 734 | |
503 | 735 | """Development VCS handler. | ||
504 | 736 | |||
505 | 737 | This isn't a handler for any VCS, but a helper to ease development and let | ||
506 | 738 | runlists point to a path that can be copied locally. | ||
507 | 739 | |||
508 | 740 | """ | ||
509 | 562 | 741 | ||
510 | 563 | def __init__(self, repo, destination=".", **kwargs): | 742 | def __init__(self, repo, destination=".", **kwargs): |
511 | 564 | super(DevHandler, self).__init__(repo, destination, **kwargs) | 743 | super(DevHandler, self).__init__(repo, destination, **kwargs) |
Looks good. Thanks.