Commit 02cad41b authored by Edward Loper's avatar Edward Loper

- Added __docformat__

- Added comments for some regexps
- If the traceback type/message don't match, then still print full
  traceback in report_failure (not just the first & last lines)
- Renamed DocTestRunner.__failure_header -> _failure_header
parent 26540c7a
...@@ -167,6 +167,7 @@ output as appeared in the initial ">>>" line that triggered it. ...@@ -167,6 +167,7 @@ output as appeared in the initial ">>>" line that triggered it.
If you execute this very file, the examples above will be found and If you execute this very file, the examples above will be found and
executed. executed.
""" """
__docformat__ = 'reStructuredText en'
__all__ = [ __all__ = [
'is_private', 'is_private',
...@@ -330,6 +331,17 @@ def _tag_msg(tag, msg, indent=' '): ...@@ -330,6 +331,17 @@ def _tag_msg(tag, msg, indent=' '):
msg = '\n'.join([indent+l for l in msg[:-1].split('\n')]) msg = '\n'.join([indent+l for l in msg[:-1].split('\n')])
return '%s:\n%s\n' % (tag, msg) return '%s:\n%s\n' % (tag, msg)
def _exception_traceback(exc_info):
"""
Return a string containing a traceback message for the given
exc_info tuple (as returned by sys.exc_info()).
"""
# Get a traceback message.
excout = StringIO()
exc_type, exc_val, exc_tb = exc_info
traceback.print_exception(exc_type, exc_val, exc_tb, file=excout)
return excout.getvalue()
# Override some StringIO methods. # Override some StringIO methods.
class _SpoofOut(StringIO): class _SpoofOut(StringIO):
def getvalue(self): def getvalue(self):
...@@ -467,6 +479,11 @@ class DocTestParser: ...@@ -467,6 +479,11 @@ class DocTestParser:
""" """
A class used to parse strings containing doctest examples. A class used to parse strings containing doctest examples.
""" """
# This regular expression is used to find doctest examples in a
# string. It defines three groups: `source` is the source code
# (including leading indentation and prompts); `indent` is the
# indentation of the first (PS1) line of the source code; and
# `want` is the expected output (including leading indentation).
_EXAMPLE_RE = re.compile(r''' _EXAMPLE_RE = re.compile(r'''
# Source consists of a PS1 line followed by zero or more PS2 lines. # Source consists of a PS1 line followed by zero or more PS2 lines.
(?P<source> (?P<source>
...@@ -479,7 +496,10 @@ class DocTestParser: ...@@ -479,7 +496,10 @@ class DocTestParser:
.*$\n? # But any other line .*$\n? # But any other line
)*) )*)
''', re.MULTILINE | re.VERBOSE) ''', re.MULTILINE | re.VERBOSE)
_IS_BLANK_OR_COMMENT = re.compile('^[ ]*(#.*)?$').match
# This regular expression matcher checks if a given string is a
# blank line or contains a single comment.
_IS_BLANK_OR_COMMENT = re.compile(r'^[ ]*(#.*)?$').match
def get_doctest(self, string, globs, name, filename, lineno): def get_doctest(self, string, globs, name, filename, lineno):
""" """
...@@ -1125,7 +1145,7 @@ class DocTestRunner: ...@@ -1125,7 +1145,7 @@ class DocTestRunner:
Report that the given example failed. Report that the given example failed.
""" """
# Print an error message. # Print an error message.
out(self.__failure_header(test, example) + out(self._failure_header(test, example) +
self._checker.output_difference(example.want, got, self._checker.output_difference(example.want, got,
self.optionflags)) self.optionflags))
...@@ -1133,16 +1153,10 @@ class DocTestRunner: ...@@ -1133,16 +1153,10 @@ class DocTestRunner:
""" """
Report that the given example raised an unexpected exception. Report that the given example raised an unexpected exception.
""" """
# Get a traceback message. out(self._failure_header(test, example) +
excout = StringIO() _tag_msg("Exception raised", _exception_traceback(exc_info)))
exc_type, exc_val, exc_tb = exc_info
traceback.print_exception(exc_type, exc_val, exc_tb, file=excout)
exception_tb = excout.getvalue()
# Print an error message.
out(self.__failure_header(test, example) +
_tag_msg("Exception raised", exception_tb))
def __failure_header(self, test, example): def _failure_header(self, test, example):
s = (self.DIVIDER + "\n" + s = (self.DIVIDER + "\n" +
_tag_msg("Failure in example", example.source)) _tag_msg("Failure in example", example.source))
if test.filename is None: if test.filename is None:
...@@ -1256,10 +1270,10 @@ class DocTestRunner: ...@@ -1256,10 +1270,10 @@ class DocTestRunner:
self.optionflags)): self.optionflags)):
# Is +exc_msg the right thing here?? # Is +exc_msg the right thing here??
self.report_success(out, test, example, self.report_success(out, test, example,
got+exc_hdr+exc_msg) got+_exception_traceback(exc_info))
else: else:
self.report_failure(out, test, example, self.report_failure(out, test, example,
got+exc_hdr+exc_msg) got+_exception_traceback(exc_info))
failures += 1 failures += 1
# Restore the option flags (in case they were modified) # Restore the option flags (in case they were modified)
......
...@@ -269,10 +269,10 @@ will return a single test (for that function's docstring): ...@@ -269,10 +269,10 @@ will return a single test (for that function's docstring):
>>> finder = doctest.DocTestFinder() >>> finder = doctest.DocTestFinder()
>>> tests = finder.find(sample_func) >>> tests = finder.find(sample_func)
>>> print tests # doctest: +ELLIPSIS >>> print tests # doctest: +ELLIPSIS
[<DocTest sample_func from ...:12 (1 example)>] [<DocTest sample_func from ...:12 (1 example)>]
>>> e = tests[0].examples[0] >>> e = tests[0].examples[0]
>>> (e.source, e.want, e.lineno) >>> (e.source, e.want, e.lineno)
('print sample_func(22)\n', '44\n', 3) ('print sample_func(22)\n', '44\n', 3)
...@@ -620,6 +620,7 @@ message is raised, then it is reported as a failure: ...@@ -620,6 +620,7 @@ message is raised, then it is reported as a failure:
... ''' ... '''
>>> test = doctest.DocTestFinder().find(f)[0] >>> test = doctest.DocTestFinder().find(f)[0]
>>> doctest.DocTestRunner(verbose=False).run(test) >>> doctest.DocTestRunner(verbose=False).run(test)
... # doctest: +ELLIPSIS
********************************************************************** **********************************************************************
Failure in example: raise ValueError, 'message' Failure in example: raise ValueError, 'message'
from line #1 of f from line #1 of f
...@@ -628,6 +629,7 @@ message is raised, then it is reported as a failure: ...@@ -628,6 +629,7 @@ message is raised, then it is reported as a failure:
ValueError: wrong message ValueError: wrong message
Got: Got:
Traceback (most recent call last): Traceback (most recent call last):
...
ValueError: message ValueError: message
(1, 1) (1, 1)
...@@ -897,7 +899,7 @@ comment of the form ``# doctest: -OPTION``: ...@@ -897,7 +899,7 @@ comment of the form ``# doctest: -OPTION``:
Option directives affect only the example that they appear with; they Option directives affect only the example that they appear with; they
do not change the options for surrounding examples: do not change the options for surrounding examples:
>>> def f(x): r''' >>> def f(x): r'''
... >>> print range(10) # Should fail: no ellipsis ... >>> print range(10) # Should fail: no ellipsis
... [0, 1, ..., 9] ... [0, 1, ..., 9]
...@@ -984,7 +986,7 @@ long as a continuation prompt is used: ...@@ -984,7 +986,7 @@ long as a continuation prompt is used:
>>> test = doctest.DocTestFinder().find(f)[0] >>> test = doctest.DocTestFinder().find(f)[0]
>>> doctest.DocTestRunner(verbose=False).run(test) >>> doctest.DocTestRunner(verbose=False).run(test)
(0, 1) (0, 1)
For examples with multi-line source, the option directive may appear For examples with multi-line source, the option directive may appear
at the end of any line: at the end of any line:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment