Merge lp:~joetalbott/utah/parser_error_handling into lp:utah

Proposed by Joe Talbott
Status: Merged
Approved by: Javier Collado
Approved revision: 760
Merged at revision: 763
Proposed branch: lp:~joetalbott/utah/parser_error_handling
Merge into: lp:utah
Diff against target: 145 lines (+68/-18)
2 files modified
docs/source/reference.rst (+6/-0)
utah/parser.py (+62/-18)
To merge this branch: bzr merge lp:~joetalbott/utah/parser_error_handling
Reviewer Review Type Date Requested Status
Javier Collado (community) Approve
Joe Talbott (community) Needs Resubmitting
Review via email: mp+135525@code.launchpad.net

Commit message

Add module level error handling and raise ParserError when necessary.

Description of the change

This branch handles schema validation errors so that the parsing process can finish.

I'm not sure if I should add my own exception class to utah.parser and have consumers of this module use that exception as an indicator of failure or use None as I'm doing in this branch. Open for discussion.

To post a comment you must log in.
Revision history for this message
Javier Collado (javier.collado) wrote :

I'm not sure about the usefulness of capturing the exceptions and printing
errors without more detail about what would be the use case for it.

If the code is expected to be used as a script, then it makes sense to do this
and also to return an error code. However, if the code is expected to be used
as a library, then the calling code could capture the exceptions itself, so it
depends on the expectations of that code.

Revision history for this message
Joe Talbott (joetalbott) wrote :

This is library code. I don't want code consumers to have to know to catch jsonschema.ValidationError or whatever. I'm going to resubmit with a utah.parser.ParseError exception that code consumers can catch and raise that on internal errors.

758. By Joe Talbott

parser - Add exception class.

Revision history for this message
Joe Talbott (joetalbott) wrote :

Please re-review. This branch now adds a ParserError exception class for consumers.

review: Needs Resubmitting
Revision history for this message
Javier Collado (javier.collado) wrote :

Since this is a small change, let me be picky and look into the documentation
strings.

Since we're using sphinx for documentation and I see you've included
information return and exception information in `UTAHParser.parse`, let's use
sphinx markup so that it shows properly in the html documentation.

To do that use (http://sphinx-doc.org/domains.html#info-field-lists):
:param <param>: to describe a parameter
:type <type>: to annotate the parameter type
:raises <exception>: to add exceptions that might be raised
:return: to describe what is being returned
:rtype: to annotate the type of the return value

You'll see that there are different options for the same markup, but if we use
the same ones it will look more consistent (actually, I've been using :throws:
instead of :raises:, but I'll fix that).

Finally, if you use the pep257 to ensure that the documentation is compliant,
then that will make me really happy.

review: Needs Fixing
Revision history for this message
Javier Collado (javier.collado) wrote :

I've created a merge request for the change from :throws: to :raises: and also
I've seen that what I've been using is :returns: (not :return:), so please us
that instead.

759. By Joe Talbott

parser - Fix docstrings and add sphinx markup.

760. By Joe Talbott

parser - Fix some leftover docstring issues.

Revision history for this message
Joe Talbott (joetalbott) wrote :

Fixed docstrings.

review: Needs Resubmitting
Revision history for this message
Javier Collado (javier.collado) wrote :

Thanks for the update.

I'm going to merge this with some pep8 related fixes and small cosmetic changes
to the docstrings. In particular, I'm going to remove the whitespace after the
triple quotes to match the examples in pep257.

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-11-26 13:32:02 +0000
3+++ docs/source/reference.rst 2012-11-29 23:26:22 +0000
4@@ -22,6 +22,12 @@
5 .. automodule:: utah.iso
6 :members:
7
8+``utah.parser``
9+----------------
10+
11+.. automodule:: utah.parser
12+ :members:
13+
14 ``utah.preseed``
15 ----------------
16
17
18=== modified file 'utah/parser.py'
19--- utah/parser.py 2012-11-21 14:59:18 +0000
20+++ utah/parser.py 2012-11-29 23:26:22 +0000
21@@ -1,3 +1,7 @@
22+"""
23+UTAH Client log parser.
24+
25+"""
26 import argparse
27 import jsonschema
28 import logging
29@@ -5,10 +9,15 @@
30 import urllib2
31 import yaml
32
33+class ParserError(Exception):
34+
35+ """ Module level parse error exception. """
36+
37+ pass
38+
39 class UTAHParser(object):
40- """
41- UTAH Client result parser class.
42- """
43+
44+ """ UTAH Client result parser class. """
45
46 COMMAND_SCHEMA = {
47 'type': 'object',
48@@ -71,13 +80,13 @@
49 }
50
51 def parse(self, logdata, as_string=False):
52- """
53- Parse utah client results.
54-
55- logdata should be either a filename or a handle to a file
56- object.
57-
58- Returns the parsed yaml data or None.
59+ """ Parse utah client results.
60+
61+ :param logdata: should be either a filename or a handle to a file object.
62+
63+ :returns: the parsed yaml data or None.
64+
65+ :raises: ParserError on exceptions.
66
67 """
68
69@@ -89,19 +98,40 @@
70 return self._parse_stream(logdata)
71
72 def _parse_stream(self, stream):
73- """ Parse client output from stream. """
74+ """ Parse client output from stream.
75+
76+ :returns: validated decoded YAML data.
77+
78+ :raises: ParseError
79+
80+ """
81 try:
82 data = yaml.load(stream)
83 except yaml.YAMLError as e:
84 logging.error(e)
85- return None
86-
87- jsonschema.validate(data, self.CLIENT_OUTPUT_SCHEMA)
88+ raise ParserError(e.message)
89+
90+ # Allow empty yaml files
91+ if data is None:
92+ return data
93+
94+ try:
95+ jsonschema.validate(data, self.CLIENT_OUTPUT_SCHEMA)
96+ except jsonschema.ValidationError as e:
97+ logging.error(e)
98+ raise ParserError(e.message)
99
100 return data
101
102 def _parse_logfile(self, logfile):
103- """ Parse client output log. """
104+ """ Parse client output log.
105+
106+ :returns: validated decoded YAML data.
107+
108+ :raises: ParseError
109+
110+ """
111+
112
113 data = None
114
115@@ -115,14 +145,28 @@
116 return data
117
118 def _parse_string(self, log_data):
119- """ Parse client data from a string. """
120+ """ Parse client data from a string.
121+
122+ :returns: validated decoded YAML data.
123+
124+ :raises: ParseError
125+
126+ """
127 try:
128 data = yaml.load(log_data)
129+
130+ # Allow empty yaml files
131+ if data is None:
132+ return data
133 except yaml.YAMLError as e:
134 logging.error(e)
135- return None
136+ raise ParserError(e.message)
137
138- jsonschema.validate(data, self.CLIENT_OUTPUT_SCHEMA)
139+ try:
140+ jsonschema.validate(data, self.CLIENT_OUTPUT_SCHEMA)
141+ except jsonschema.ValidationError as e:
142+ logging.error(e)
143+ raise ParserError(e.message)
144
145 return data
146

Subscribers

People subscribed via source and target branches