Merge lp:~javier.collado/utah/utah_client_common_docs into lp:utah

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
Reviewer Review Type Date Requested Status
Joe Talbott (community) Approve
UTAH Dev Pending
Review via email: mp+150740@code.launchpad.net

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.
Revision history for this message
Joe Talbott (joetalbott) wrote :

Looks good. Thanks.

review: Approve

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
6 .. automodule:: utah.client
7
8+``utah.client.common``
9+----------------------
10+
11 .. automodule:: utah.client.common
12 :members:
13
14
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 # You should have received a copy of the GNU General Public License along
20 # with this program. If not, see <http://www.gnu.org/licenses/>.
21
22-"""
23-Common methods.
24-"""
25+"""UTAH client common classes and functions."""
26
27 import datetime
28 import re
29@@ -75,16 +73,39 @@
30
31
32 def do_nothing(_obj=None):
33- """
34- Do nothing method used a placeholder for save_state_callbacks.
35- """
36- pass
37+ """Placeholder for save_state_callbacks.
38+
39+ .. seealso:: :class:`.TestSuite`, :class:`.TestCase`
40+
41+ """
42
43
44 # Inspired by:
45 # http://stackoverflow.com/a/3326559
46 def run_cmd(command, cwd=None, timeout=0, cmd_type=CMD_TC_TEST, run_as=None,
47 battery_measurements=False):
48+ """Run command and return result using the client's format.
49+
50+ :param command: Command as it would be written in a console
51+ :type command: str
52+ :param cwd: Current working directory path
53+ :type cwd: str
54+ :param timeout:
55+ Maximum amount of time in seconds to wait for the command to complete
56+ :type timeout: int
57+ :param cmd_type: Command type as displayed in the result object
58+ :type cmd_type: str
59+ :param run_as: Username to use to run the command
60+ :type run_as: int
61+ :param battery_measurements:
62+ Flag to configure when to get battery related information
63+ :type battery_measurements: bool
64+ :returns: Command execution result
65+ :rtype: dict
66+
67+ .. seealso:: :func:`make_result`
68+
69+ """
70
71 if run_as is not None:
72 # add -n so sudo will not prompt for a password on the tty
73@@ -172,6 +193,13 @@
74 Make sure that byte strings are used only for ascii data and unicode
75 strings for strings using any other encoding.
76
77+ :param value: Data string that should be normalized
78+ :type value: str
79+ :param encoding: Encoding used to decode the given string
80+ :type encoding: str
81+ :returns: Data string reencoded using in ascii if possible
82+ :rtype: str
83+
84 """
85 unicode_value = value.decode(encoding)
86 try:
87@@ -185,10 +213,37 @@
88 # TODO: it might make sense to have a result object that keeps track of
89 # test pass, fail, error and serializes it's data.
90 def make_result(command, retcode, stdout='', stderr='', start_time='',
91- time_delta='', cmd_type=CMD_TC_TEST, user="unknown",
92+ time_delta='', cmd_type=CMD_TC_TEST, user='unknown',
93 start_battery=None, end_battery=None):
94- """
95- Make a result dictionary.
96+ """Make a result data structure.
97+
98+ .. note::
99+ Battery information will only be included if some value is passed as
100+ argument.
101+
102+ :param command: Command that was executed
103+ :type command: str
104+ :param retcode: Return code
105+ :type retcode: int
106+ :param stdout: Standard output
107+ :type stdout: str
108+ :param stderr: Standard error
109+ :type stderr: str
110+ :param start_time: Time in which command execution started
111+ :type start_time: str
112+ :param time_delta: Amount of time that the command took to complete
113+ :type time_delta: str
114+ :param cmd_type: Command type to be displayed in the report
115+ :type cmd_type: str
116+ :param user: User name the executed the command
117+ :type user: str
118+ :param start_battery: Battery information before running the command
119+ :type start_battery: dict
120+ :param end_battery: Battery information after running the command
121+ :type end_battery: dict
122+ :returns: Result data
123+ :rtype: dict
124+
125 """
126 res = {
127 'command': command,
128@@ -212,6 +267,14 @@
129
130
131 def get_process_children(pid):
132+ """Get the children processes of a given one.
133+
134+ :param pid: Process ID of the parent process
135+ :type pid: int
136+ :returns: Process ID for the childern processes
137+ :rtype: list(int)
138+
139+ """
140 p = subprocess.Popen('ps --no-headers -o pid --ppid %d' % pid, shell=True,
141 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
142 stdout, _stderr = p.communicate()
143@@ -220,9 +283,18 @@
144
145
146 def parse_yaml_file(filename):
147- """
148- Parse yaml file and raise exception with error location
149- in case of error
150+ """Parse yaml file.
151+
152+ :param filename: Path to the file that should be read
153+ :type filename: str
154+ :returns: Parsed data
155+ :rtype: object
156+ :raises YAMLParsingError:
157+ If there's a problem while parsing the file with the information about
158+ where in the file the problem was detected.
159+
160+ .. seealso:: :func:`parse_control_file`
161+
162 """
163 try:
164 with open(filename, 'r') as fp:
165@@ -247,7 +319,16 @@
166 # Validator that sets values to defaults as explained in:
167 # https://github.com/Julian/jsonschema/issues/4
168 class DefaultValidator(jsonschema.Validator):
169+
170+ """jsonschema validator that sets default values.
171+
172+ During the validation, if some field is missing in the data, it will be set
173+ to the default value specified in the schema if defined.
174+
175+ """
176+
177 def validate_properties(self, properties, instance, schema):
178+ """Set missing properties to default value."""
179 (super(DefaultValidator, self)
180 .validate_properties(properties, instance, schema))
181 instance.update((k, v['default'])
182@@ -256,8 +337,19 @@
183
184
185 def parse_control_file(filename, schema):
186- """
187- Parse a control file and check against the schema
188+ """Parse a control file and check against a jsonschema.
189+
190+ :param filename: Path to the yaml file to be parsed
191+ :type filename: str
192+ :param schema: jsonschema to validate data against
193+ :type schema: dict
194+ :returns: Parsed data
195+ :rtype: object
196+ :raises jsonschema.ValidationError:
197+ If file contents doesn't follow the schema definitions
198+
199+ .. seealso:: :func:`parse_yaml_file`, :class:`DefaultValidator`
200+
201 """
202 control_data = parse_yaml_file(filename)
203 validator = DefaultValidator()
204@@ -266,8 +358,17 @@
205
206
207 def debug_print(data, force=False):
208- """
209- Print debugging information if CONFIG['DEBUG'] is defined and True
210+ """Print debugging information according to ``CONFIG['DEBUG']`` value.
211+
212+ Data will be printed with the ``DEBUG:`` string prepended to it.
213+
214+ :param data: Data to be printed
215+ :type data: object
216+ :param force: Print data regardless of the configuration
217+ :type force: bool
218+ :returns: Whether something was printed or not
219+ :rtype: bool
220+
221 """
222 try:
223 debug = CONFIG['DEBUG']
224@@ -284,8 +385,11 @@
225
226
227 def raise_privileges(orig_privs):
228- """
229- Raise privileges to original effective privileges.
230+ """Raise privileges to original effective privileges.
231+
232+ :param orig_privs: Original privileges
233+ :type orig_privs: dict
234+
235 """
236 os.seteuid(orig_privs['euid'])
237 os.setegid(orig_privs['egid'])
238@@ -293,12 +397,18 @@
239
240
241 def drop_privileges(user='nobody', group='nogroup', full=False):
242- """
243- Change user and/or group to decrease privileges.
244+ """Change user and/or group to decrease privileges.
245
246 Currently only drops effective privileges.
247
248- Returns a dictionary of the original values.
249+ :param user: User name to change to.
250+ :type user: str
251+ :param group: Group name to change to.
252+ :type group: str
253+
254+ :returns: Original prrivileges
255+ :rtype: dict
256+
257 """
258
259 orig_privs = {}
260@@ -333,8 +443,13 @@
261
262
263 def gather_artifacts(extras=None, excludes=None):
264- """
265- Include a set of useful artifacts (i.e. files) for the logs.
266+ """Print files contents, so that it's included in the logs.
267+
268+ :param extras: Path to files to be included in the artifacts
269+ :type extras: list(str)
270+ :param excludes: Path to files to be exluded from the artifacts
271+ :type excludes: list(str)
272+
273 """
274 if extras is None:
275 extras = []
276@@ -366,12 +481,14 @@
277
278
279 def get_media_info():
280- """
281- Get the contents of the media-info file if available.
282-
283- NOTE: This is only a best-effort approach.
284-
285- Returns the contents of the media-info file or None.
286+ """Get the contents of the media-info file if available.
287+
288+ :returns:
289+ The contents of the media-info file or ``'unknown'`` if not available.
290+ :rtype: str
291+
292+ .. note:: This is only a best-effort approach.
293+
294 """
295
296 filename = '/var/log/installer/media-info'
297@@ -386,12 +503,13 @@
298
299
300 def get_product_uuid():
301- """
302- Get the product_uuid of the machine under test.
303-
304- NOTE: This is only a best-effort approach.
305-
306- Returns the contents of the product_uuid file or None.
307+ """Get the product_uuid of the machine under test.
308+
309+ :returns:
310+ The contents of the product_uuid file or ``None`` if not available.
311+
312+ .. note:: This is only a best-effort approach.
313+
314 """
315
316 filename = '/sys/class/dmi/id/product_uuid'
317@@ -406,8 +524,13 @@
318
319
320 def get_host_info():
321- """
322- Get host info, useful for debugging.
323+ """Get host info, useful for debugging.
324+
325+ :returns: Host uname, media-info and product_uuid together
326+ :rtype: dict
327+
328+ .. seealso:: :func:`get_media_info`, :func:`get_product_uuid`
329+
330 """
331
332 retval = {}
333@@ -421,10 +544,11 @@
334
335
336 def get_arch():
337- """
338- The host's architecture.
339-
340- Returns the human readable architecture or 'unknown'.
341+ """Get the host's architecture.
342+
343+ :returns: The human readable architecture or ``'unknown'``
344+ :rtype: str
345+
346 """
347 arches = {
348 'x86_64': 'amd64',
349@@ -436,15 +560,20 @@
350
351
352 def get_release():
353- """
354- The host's release name (i.e. precise, quantal, etc.)
355- """
356- return platform.dist()[2]
357+ """Get the host's release name.
358+
359+ :returns: Release name (i.e. quantal, raring, etc.)
360+ :rtype: str
361+
362+ """
363+ return platform.linux_distribution()[2]
364
365
366 def get_api_config():
367- """
368- Parse the client configuration file for API configuration data.
369+ """Parse the client configuration file for API configuration data.
370+
371+ :returns: The value for the ``API`` field in the client configuration file.
372+
373 """
374
375 data = {}
376@@ -457,6 +586,14 @@
377
378
379 def get_build_number():
380+ """Get build number.
381+
382+ :returns: Build number as according to media-info or ``'?'`` if not found
383+ :rtype: str
384+
385+ .. seealso:: :func:`get_host_info`
386+
387+ """
388 host_info = get_host_info()
389 pattern = re.compile('.*\(([0-9.]+)\)$')
390 match = pattern.match(host_info['media-info'])
391@@ -469,8 +606,19 @@
392
393
394 class VCSHandler(object):
395- """
396- Base class for Version Ccontrol System support.
397+
398+ """Base class for Version Control System support.
399+
400+ :param repo: Repository location
401+ :type repo: str
402+ :param destination:
403+ Local directory where the repository should be made available
404+ :type destination: str
405+ :param battery_measurements:
406+ Whether battery information should be gathered when running any of the
407+ VCS commands
408+ :type battery_measurements: bool
409+
410 """
411
412 def __init__(self, repo, destination='', battery_measurements=False):
413@@ -479,8 +627,18 @@
414 self.battery_measurements = battery_measurements
415
416 def get(self, directory=REPO_DEFAULT_DIR):
417- """
418- Method to retrieve a copy of the repository
419+ """Execute VCS get command.
420+
421+ The get command will make a copy of a given repository to the directory
422+ specified as destination.
423+
424+ :param directory: Working directory
425+ :type directory: str
426+ :returns: Get command execution result
427+ :rtype: dict
428+
429+ .. seealso:: :func:`run_cmd`
430+
431 """
432 return run_cmd(self.get_command,
433 cwd=directory,
434@@ -488,8 +646,15 @@
435 battery_measurements=self.battery_measurements)
436
437 def revision(self, directory=REPO_DEFAULT_DIR):
438- """
439- Return the revision identifier.
440+ """Execute revision command.
441+
442+ :param directory: Working directory
443+ :type directory: str
444+ :returns: Revision command execution result.
445+ :rtype: dict
446+
447+ .. seealso:: :func:`run_cmd`, :meth:`get_revision`
448+
449 """
450 return run_cmd(self.rev_command,
451 cwd=directory,
452@@ -497,8 +662,18 @@
453 battery_measurements=self.battery_measurements)
454
455 def get_revision(self, directory=REPO_DEFAULT_DIR):
456- """
457- get the revision information
458+ """Print revision information.
459+
460+ This is a wrapper around :meth:`revision` to make sure that the command
461+ returned a success code.
462+
463+ :param directory: Working directory
464+ :type directory: str
465+ :returns: Revision command returncode
466+ :rtype: int
467+
468+ .. seealso:: :meth:`revision`
469+
470 """
471 retval = None
472 result = self.revision(directory=directory)
473@@ -512,9 +687,8 @@
474
475
476 class BzrHandler(VCSHandler):
477- """
478- bazaar handler.
479- """
480+
481+ """Bazaar VCS handler."""
482
483 def __init__(self, repo, branch=True, options="", destination="",
484 **kwargs):
485@@ -540,9 +714,8 @@
486
487
488 class GitHandler(VCSHandler):
489- """
490- git handler.
491- """
492+
493+ """Git VCS handler."""
494
495 def __init__(self, repo, options="", destination="", **kwargs):
496 super(GitHandler, self).__init__(repo, destination, **kwargs)
497@@ -558,7 +731,13 @@
498
499
500 class DevHandler(VCSHandler):
501- """ Copy from a local directory for development. """
502+
503+ """Development VCS handler.
504+
505+ This isn't a handler for any VCS, but a helper to ease development and let
506+ runlists point to a path that can be copied locally.
507+
508+ """
509
510 def __init__(self, repo, destination=".", **kwargs):
511 super(DevHandler, self).__init__(repo, destination, **kwargs)

Subscribers

People subscribed via source and target branches