Improved documentation error handling

This commit is contained in:
Matt Martz 2016-02-20 11:37:55 -06:00 committed by John Barker
parent ddf0474a76
commit 60a2165987

View file

@ -74,7 +74,7 @@ class Validator(object):
for trace in self.traces: for trace in self.traces:
print('TRACE:') print('TRACE:')
print(trace) print('\n '.join((' %s' % trace).splitlines()))
for error in self.errors: for error in self.errors:
print('ERROR: %s' % error) print('ERROR: %s' % error)
ret.append(1) ret.append(1)
@ -339,6 +339,26 @@ class ModuleValidator(Validator):
return docs return docs
def _validate_docs(self): def _validate_docs(self):
doc_info = self._get_docs()
try:
doc = yaml.safe_load(doc_info['DOCUMENTATION']['value'])
except yaml.YAMLError as e:
doc = None
# This offsets the error line number to where the
# DOCUMENTATION starts so we can just go to that line in the
# module
e.problem_mark.line += (
doc_info['DOCUMENTATION']['lineno'] - 1
)
e.problem_mark.name = '%s.DOCUMENTATION' % self.name
self.traces.append(e)
self.errors.append('DOCUMENTATION is not valid YAML. Line %d '
'column %d' %
(e.problem_mark.line + 1,
e.problem_mark.column + 1))
except AttributeError:
self.errors.append('No DOCUMENTATION provided')
else:
sys_stdout = sys.stdout sys_stdout = sys.stdout
sys_stderr = sys.stderr sys_stderr = sys.stderr
sys.stdout = sys.stderr = buf = StringIO() sys.stdout = sys.stderr = buf = StringIO()
@ -346,46 +366,32 @@ class ModuleValidator(Validator):
assert buf assert buf
setattr(sys.stdout, 'encoding', sys_stdout.encoding) setattr(sys.stdout, 'encoding', sys_stdout.encoding)
setattr(sys.stderr, 'encoding', sys_stderr.encoding) setattr(sys.stderr, 'encoding', sys_stderr.encoding)
doc_info = self._get_docs()
try: try:
doc, examples, ret = get_docstring(self.path, verbose=True) get_docstring(self.path, verbose=True)
trace = None except AssertionError:
except yaml.YAMLError as e: fragment = doc['extends_documentation_fragment']
doc = None self.errors.append('DOCUMENTATION fragment missing: %s' % fragment)
examples = doc_info['EXAMPLES']['value'] except Exception as e:
ret = doc_info['RETURN']['value'] self.traces.append(e)
trace = e self.errors.append('Unknown DOCUMENTATION error, see TRACE')
finally: finally:
sys.stdout = sys_stdout sys.stdout = sys_stdout
sys.stderr = sys_stderr sys.stderr = sys_stderr
if trace:
# This offsets the error line number to where the
# DOCUMENTATION starts so we can just go to that line in the
# module
trace.problem_mark.line += (
doc_info['DOCUMENTATION']['lineno'] - 1
)
trace.problem_mark.name = '%s.DOCUMENTATION' % self.name
self.traces.append(trace)
self.errors.append('DOCUMENTATION is not valid YAML. Line %d '
'column %d' %
(trace.problem_mark.line + 1,
trace.problem_mark.column + 1))
if not bool(doc):
self.errors.append('No DOCUMENTATION provided')
else:
self._check_version_added(doc) self._check_version_added(doc)
self._check_for_new_args(doc) self._check_for_new_args(doc)
if not bool(examples):
if not bool(doc_info['EXAMPLES']['value']):
self.errors.append('No EXAMPLES provided') self.errors.append('No EXAMPLES provided')
if not bool(ret):
if not bool(doc_info['RETURN']['value']):
if self._is_new_module(): if self._is_new_module():
self.errors.append('No RETURN documentation provided') self.errors.append('No RETURN documentation provided')
else: else:
self.warnings.append('No RETURN provided') self.warnings.append('No RETURN provided')
else: else:
try: try:
yaml.safe_load(ret) yaml.safe_load(doc_info['RETURN']['value'])
except yaml.YAMLError as e: except yaml.YAMLError as e:
e.problem_mark.line += ( e.problem_mark.line += (
doc_info['RETURN']['lineno'] - 1 doc_info['RETURN']['lineno'] - 1
@ -429,9 +435,30 @@ class ModuleValidator(Validator):
if self._is_new_module(): if self._is_new_module():
return return
sys_stdout = sys.stdout
sys_stderr = sys.stderr
sys.stdout = sys.stderr = buf = StringIO()
# instead of adding noqa to the above, do something with buf
assert buf
setattr(sys.stdout, 'encoding', sys_stdout.encoding)
setattr(sys.stderr, 'encoding', sys_stderr.encoding)
try:
existing = module_loader.find_plugin(self.name, mod_type='.py') existing = module_loader.find_plugin(self.name, mod_type='.py')
existing_doc, _, _ = get_docstring(existing, verbose=True) existing_doc, _, _ = get_docstring(existing, verbose=True)
existing_options = existing_doc.get('options', {}) existing_options = existing_doc.get('options', {})
except AssertionError:
fragment = doc['extends_documentation_fragment']
self.errors.append('Existing DOCUMENTATION fragment missing: %s' %
fragment)
return
except Exception as e:
self.traces.append(e)
self.errors.append('Unknown existing DOCUMENTATION error, see '
'TRACE')
return
finally:
sys.stdout = sys_stdout
sys.stderr = sys_stderr
options = doc.get('options', {}) options = doc.get('options', {})