1a380bf10Simarom# Module doctest.
2a380bf10Simarom# Released to the public domain 16-Jan-2001, by Tim Peters (tim@python.org).
3a380bf10Simarom# Major enhancements and refactoring by:
4a380bf10Simarom#     Jim Fulton
5a380bf10Simarom#     Edward Loper
6a380bf10Simarom
7a380bf10Simarom# Provided as-is; use at your own risk; no warranty; no promises; enjoy!
8a380bf10Simarom#
9a380bf10Simarom# Modified for inclusion in nose to provide support for DocFileTest in
10a380bf10Simarom# python 2.3:
11a380bf10Simarom#
12a380bf10Simarom# - all doctests removed from module (they fail under 2.3 and 2.5)
13a380bf10Simarom# - now handles the $py.class extension when ran under Jython
14a380bf10Simarom
15a380bf10Simaromr"""Module doctest -- a framework for running examples in docstrings.
16a380bf10Simarom
17a380bf10SimaromIn simplest use, end each module M to be tested with:
18a380bf10Simarom
19a380bf10Simaromdef _test():
20a380bf10Simarom    import doctest
21a380bf10Simarom    doctest.testmod()
22a380bf10Simarom
23a380bf10Simaromif __name__ == "__main__":
24a380bf10Simarom    _test()
25a380bf10Simarom
26a380bf10SimaromThen running the module as a script will cause the examples in the
27a380bf10Simaromdocstrings to get executed and verified:
28a380bf10Simarom
29a380bf10Simarompython M.py
30a380bf10Simarom
31a380bf10SimaromThis won't display anything unless an example fails, in which case the
32a380bf10Simaromfailing example(s) and the cause(s) of the failure(s) are printed to stdout
33a380bf10Simarom(why not stderr? because stderr is a lame hack <0.2 wink>), and the final
34a380bf10Simaromline of output is "Test failed.".
35a380bf10Simarom
36a380bf10SimaromRun it with the -v switch instead:
37a380bf10Simarom
38a380bf10Simarompython M.py -v
39a380bf10Simarom
40a380bf10Simaromand a detailed report of all examples tried is printed to stdout, along
41a380bf10Simaromwith assorted summaries at the end.
42a380bf10Simarom
43a380bf10SimaromYou can force verbose mode by passing "verbose=True" to testmod, or prohibit
44a380bf10Simaromit by passing "verbose=False".  In either of those cases, sys.argv is not
45a380bf10Simaromexamined by testmod.
46a380bf10Simarom
47a380bf10SimaromThere are a variety of other ways to run doctests, including integration
48a380bf10Simaromwith the unittest framework, and support for running non-Python text
49a380bf10Simaromfiles containing doctests.  There are also many ways to override parts
50a380bf10Simaromof doctest's default behaviors.  See the Library Reference Manual for
51a380bf10Simaromdetails.
52a380bf10Simarom"""
53a380bf10Simarom
54a380bf10Simarom__docformat__ = 'reStructuredText en'
55a380bf10Simarom
56a380bf10Simarom__all__ = [
57a380bf10Simarom    # 0, Option Flags
58a380bf10Simarom    'register_optionflag',
59a380bf10Simarom    'DONT_ACCEPT_TRUE_FOR_1',
60a380bf10Simarom    'DONT_ACCEPT_BLANKLINE',
61a380bf10Simarom    'NORMALIZE_WHITESPACE',
62a380bf10Simarom    'ELLIPSIS',
63a380bf10Simarom    'IGNORE_EXCEPTION_DETAIL',
64a380bf10Simarom    'COMPARISON_FLAGS',
65a380bf10Simarom    'REPORT_UDIFF',
66a380bf10Simarom    'REPORT_CDIFF',
67a380bf10Simarom    'REPORT_NDIFF',
68a380bf10Simarom    'REPORT_ONLY_FIRST_FAILURE',
69a380bf10Simarom    'REPORTING_FLAGS',
70a380bf10Simarom    # 1. Utility Functions
71a380bf10Simarom    'is_private',
72a380bf10Simarom    # 2. Example & DocTest
73a380bf10Simarom    'Example',
74a380bf10Simarom    'DocTest',
75a380bf10Simarom    # 3. Doctest Parser
76a380bf10Simarom    'DocTestParser',
77a380bf10Simarom    # 4. Doctest Finder
78a380bf10Simarom    'DocTestFinder',
79a380bf10Simarom    # 5. Doctest Runner
80a380bf10Simarom    'DocTestRunner',
81a380bf10Simarom    'OutputChecker',
82a380bf10Simarom    'DocTestFailure',
83a380bf10Simarom    'UnexpectedException',
84a380bf10Simarom    'DebugRunner',
85a380bf10Simarom    # 6. Test Functions
86a380bf10Simarom    'testmod',
87a380bf10Simarom    'testfile',
88a380bf10Simarom    'run_docstring_examples',
89a380bf10Simarom    # 7. Tester
90a380bf10Simarom    'Tester',
91a380bf10Simarom    # 8. Unittest Support
92a380bf10Simarom    'DocTestSuite',
93a380bf10Simarom    'DocFileSuite',
94a380bf10Simarom    'set_unittest_reportflags',
95a380bf10Simarom    # 9. Debugging Support
96a380bf10Simarom    'script_from_examples',
97a380bf10Simarom    'testsource',
98a380bf10Simarom    'debug_src',
99a380bf10Simarom    'debug',
100a380bf10Simarom]
101a380bf10Simarom
102a380bf10Simaromimport __future__
103a380bf10Simarom
104a380bf10Simaromimport sys, traceback, inspect, linecache, os, re
105a380bf10Simaromimport unittest, difflib, pdb, tempfile
106a380bf10Simaromimport warnings
107a380bf10Simaromfrom io import StringIO
108a380bf10Simarom
109a380bf10Simarom# Don't whine about the deprecated is_private function in this
110a380bf10Simarom# module's tests.
111a380bf10Simaromwarnings.filterwarnings("ignore", "is_private", DeprecationWarning,
112a380bf10Simarom                        __name__, 0)
113a380bf10Simarom
114a380bf10Simarom# There are 4 basic classes:
115a380bf10Simarom#  - Example: a <source, want> pair, plus an intra-docstring line number.
116a380bf10Simarom#  - DocTest: a collection of examples, parsed from a docstring, plus
117a380bf10Simarom#    info about where the docstring came from (name, filename, lineno).
118a380bf10Simarom#  - DocTestFinder: extracts DocTests from a given object's docstring and
119a380bf10Simarom#    its contained objects' docstrings.
120a380bf10Simarom#  - DocTestRunner: runs DocTest cases, and accumulates statistics.
121a380bf10Simarom#
122a380bf10Simarom# So the basic picture is:
123a380bf10Simarom#
124a380bf10Simarom#                             list of:
125a380bf10Simarom# +------+                   +---------+                   +-------+
126a380bf10Simarom# |object| --DocTestFinder-> | DocTest | --DocTestRunner-> |results|
127a380bf10Simarom# +------+                   +---------+                   +-------+
128a380bf10Simarom#                            | Example |
129a380bf10Simarom#                            |   ...   |
130a380bf10Simarom#                            | Example |
131a380bf10Simarom#                            +---------+
132a380bf10Simarom
133a380bf10Simarom# Option constants.
134a380bf10Simarom
135a380bf10SimaromOPTIONFLAGS_BY_NAME = {}
136a380bf10Simaromdef register_optionflag(name):
137a380bf10Simarom    # Create a new flag unless `name` is already known.
138a380bf10Simarom    return OPTIONFLAGS_BY_NAME.setdefault(name, 1 << len(OPTIONFLAGS_BY_NAME))
139a380bf10Simarom
140a380bf10SimaromDONT_ACCEPT_TRUE_FOR_1 = register_optionflag('DONT_ACCEPT_TRUE_FOR_1')
141a380bf10SimaromDONT_ACCEPT_BLANKLINE = register_optionflag('DONT_ACCEPT_BLANKLINE')
142a380bf10SimaromNORMALIZE_WHITESPACE = register_optionflag('NORMALIZE_WHITESPACE')
143a380bf10SimaromELLIPSIS = register_optionflag('ELLIPSIS')
144a380bf10SimaromIGNORE_EXCEPTION_DETAIL = register_optionflag('IGNORE_EXCEPTION_DETAIL')
145a380bf10Simarom
146a380bf10SimaromCOMPARISON_FLAGS = (DONT_ACCEPT_TRUE_FOR_1 |
147a380bf10Simarom                    DONT_ACCEPT_BLANKLINE |
148a380bf10Simarom                    NORMALIZE_WHITESPACE |
149a380bf10Simarom                    ELLIPSIS |
150a380bf10Simarom                    IGNORE_EXCEPTION_DETAIL)
151a380bf10Simarom
152a380bf10SimaromREPORT_UDIFF = register_optionflag('REPORT_UDIFF')
153a380bf10SimaromREPORT_CDIFF = register_optionflag('REPORT_CDIFF')
154a380bf10SimaromREPORT_NDIFF = register_optionflag('REPORT_NDIFF')
155a380bf10SimaromREPORT_ONLY_FIRST_FAILURE = register_optionflag('REPORT_ONLY_FIRST_FAILURE')
156a380bf10Simarom
157a380bf10SimaromREPORTING_FLAGS = (REPORT_UDIFF |
158a380bf10Simarom                   REPORT_CDIFF |
159a380bf10Simarom                   REPORT_NDIFF |
160a380bf10Simarom                   REPORT_ONLY_FIRST_FAILURE)
161a380bf10Simarom
162a380bf10Simarom# Special string markers for use in `want` strings:
163a380bf10SimaromBLANKLINE_MARKER = '<BLANKLINE>'
164a380bf10SimaromELLIPSIS_MARKER = '...'
165a380bf10Simarom
166a380bf10Simarom######################################################################
167a380bf10Simarom## Table of Contents
168a380bf10Simarom######################################################################
169a380bf10Simarom#  1. Utility Functions
170a380bf10Simarom#  2. Example & DocTest -- store test cases
171a380bf10Simarom#  3. DocTest Parser -- extracts examples from strings
172a380bf10Simarom#  4. DocTest Finder -- extracts test cases from objects
173a380bf10Simarom#  5. DocTest Runner -- runs test cases
174a380bf10Simarom#  6. Test Functions -- convenient wrappers for testing
175a380bf10Simarom#  7. Tester Class -- for backwards compatibility
176a380bf10Simarom#  8. Unittest Support
177a380bf10Simarom#  9. Debugging Support
178a380bf10Simarom# 10. Example Usage
179a380bf10Simarom
180a380bf10Simarom######################################################################
181a380bf10Simarom## 1. Utility Functions
182a380bf10Simarom######################################################################
183a380bf10Simarom
184a380bf10Simaromdef is_private(prefix, base):
185a380bf10Simarom    """prefix, base -> true iff name prefix + "." + base is "private".
186a380bf10Simarom
187a380bf10Simarom    Prefix may be an empty string, and base does not contain a period.
188a380bf10Simarom    Prefix is ignored (although functions you write conforming to this
189a380bf10Simarom    protocol may make use of it).
190a380bf10Simarom    Return true iff base begins with an (at least one) underscore, but
191a380bf10Simarom    does not both begin and end with (at least) two underscores.
192a380bf10Simarom    """
193a380bf10Simarom    warnings.warn("is_private is deprecated; it wasn't useful; "
194a380bf10Simarom                  "examine DocTestFinder.find() lists instead",
195a380bf10Simarom                  DeprecationWarning, stacklevel=2)
196a380bf10Simarom    return base[:1] == "_" and not base[:2] == "__" == base[-2:]
197a380bf10Simarom
198a380bf10Simaromdef _extract_future_flags(globs):
199a380bf10Simarom    """
200a380bf10Simarom    Return the compiler-flags associated with the future features that
201a380bf10Simarom    have been imported into the given namespace (globs).
202a380bf10Simarom    """
203a380bf10Simarom    flags = 0
204a380bf10Simarom    for fname in __future__.all_feature_names:
205a380bf10Simarom        feature = globs.get(fname, None)
206a380bf10Simarom        if feature is getattr(__future__, fname):
207a380bf10Simarom            flags |= feature.compiler_flag
208a380bf10Simarom    return flags
209a380bf10Simarom
210a380bf10Simaromdef _normalize_module(module, depth=2):
211a380bf10Simarom    """
212a380bf10Simarom    Return the module specified by `module`.  In particular:
213a380bf10Simarom      - If `module` is a module, then return module.
214a380bf10Simarom      - If `module` is a string, then import and return the
215a380bf10Simarom        module with that name.
216a380bf10Simarom      - If `module` is None, then return the calling module.
217a380bf10Simarom        The calling module is assumed to be the module of
218a380bf10Simarom        the stack frame at the given depth in the call stack.
219a380bf10Simarom    """
220a380bf10Simarom    if inspect.ismodule(module):
221a380bf10Simarom        return module
222a380bf10Simarom    elif isinstance(module, str):
223a380bf10Simarom        return __import__(module, globals(), locals(), ["*"])
224a380bf10Simarom    elif module is None:
225a380bf10Simarom        return sys.modules[sys._getframe(depth).f_globals['__name__']]
226a380bf10Simarom    else:
227a380bf10Simarom        raise TypeError("Expected a module, string, or None")
228a380bf10Simarom
229a380bf10Simaromdef _indent(s, indent=4):
230a380bf10Simarom    """
231a380bf10Simarom    Add the given number of space characters to the beginning every
232a380bf10Simarom    non-blank line in `s`, and return the result.
233a380bf10Simarom    """
234a380bf10Simarom    # This regexp matches the start of non-blank lines:
235a380bf10Simarom    return re.sub('(?m)^(?!$)', indent*' ', s)
236a380bf10Simarom
237a380bf10Simaromdef _exception_traceback(exc_info):
238a380bf10Simarom    """
239a380bf10Simarom    Return a string containing a traceback message for the given
240a380bf10Simarom    exc_info tuple (as returned by sys.exc_info()).
241a380bf10Simarom    """
242a380bf10Simarom    # Get a traceback message.
243a380bf10Simarom    excout = StringIO()
244a380bf10Simarom    exc_type, exc_val, exc_tb = exc_info
245a380bf10Simarom    traceback.print_exception(exc_type, exc_val, exc_tb, file=excout)
246a380bf10Simarom    return excout.getvalue()
247a380bf10Simarom
248a380bf10Simarom# Override some StringIO methods.
249a380bf10Simaromclass _SpoofOut(StringIO):
250a380bf10Simarom    def getvalue(self):
251a380bf10Simarom        result = StringIO.getvalue(self)
252a380bf10Simarom        # If anything at all was written, make sure there's a trailing
253a380bf10Simarom        # newline.  There's no way for the expected output to indicate
254a380bf10Simarom        # that a trailing newline is missing.
255a380bf10Simarom        if result and not result.endswith("\n"):
256a380bf10Simarom            result += "\n"
257a380bf10Simarom        # Prevent softspace from screwing up the next test case, in
258a380bf10Simarom        # case they used print with a trailing comma in an example.
259a380bf10Simarom        if hasattr(self, "softspace"):
260a380bf10Simarom            del self.softspace
261a380bf10Simarom        return result
262a380bf10Simarom
263a380bf10Simarom    def truncate(self,   size=None):
264a380bf10Simarom        StringIO.truncate(self, size)
265a380bf10Simarom        if hasattr(self, "softspace"):
266a380bf10Simarom            del self.softspace
267a380bf10Simarom
268a380bf10Simarom# Worst-case linear-time ellipsis matching.
269a380bf10Simaromdef _ellipsis_match(want, got):
270a380bf10Simarom    if ELLIPSIS_MARKER not in want:
271a380bf10Simarom        return want == got
272a380bf10Simarom
273a380bf10Simarom    # Find "the real" strings.
274a380bf10Simarom    ws = want.split(ELLIPSIS_MARKER)
275a380bf10Simarom    assert len(ws) >= 2
276a380bf10Simarom
277a380bf10Simarom    # Deal with exact matches possibly needed at one or both ends.
278a380bf10Simarom    startpos, endpos = 0, len(got)
279a380bf10Simarom    w = ws[0]
280a380bf10Simarom    if w:   # starts with exact match
281a380bf10Simarom        if got.startswith(w):
282a380bf10Simarom            startpos = len(w)
283a380bf10Simarom            del ws[0]
284a380bf10Simarom        else:
285a380bf10Simarom            return False
286a380bf10Simarom    w = ws[-1]
287a380bf10Simarom    if w:   # ends with exact match
288a380bf10Simarom        if got.endswith(w):
289a380bf10Simarom            endpos -= len(w)
290a380bf10Simarom            del ws[-1]
291a380bf10Simarom        else:
292a380bf10Simarom            return False
293a380bf10Simarom
294a380bf10Simarom    if startpos > endpos:
295a380bf10Simarom        # Exact end matches required more characters than we have, as in
296a380bf10Simarom        # _ellipsis_match('aa...aa', 'aaa')
297a380bf10Simarom        return False
298a380bf10Simarom
299a380bf10Simarom    # For the rest, we only need to find the leftmost non-overlapping
300a380bf10Simarom    # match for each piece.  If there's no overall match that way alone,
301a380bf10Simarom    # there's no overall match period.
302a380bf10Simarom    for w in ws:
303a380bf10Simarom        # w may be '' at times, if there are consecutive ellipses, or
304a380bf10Simarom        # due to an ellipsis at the start or end of `want`.  That's OK.
305a380bf10Simarom        # Search for an empty string succeeds, and doesn't change startpos.
306a380bf10Simarom        startpos = got.find(w, startpos, endpos)
307a380bf10Simarom        if startpos < 0:
308a380bf10Simarom            return False
309a380bf10Simarom        startpos += len(w)
310a380bf10Simarom
311a380bf10Simarom    return True
312a380bf10Simarom
313a380bf10Simaromdef _comment_line(line):
314a380bf10Simarom    "Return a commented form of the given line"
315a380bf10Simarom    line = line.rstrip()
316a380bf10Simarom    if line:
317a380bf10Simarom        return '# '+line
318a380bf10Simarom    else:
319a380bf10Simarom        return '#'
320a380bf10Simarom
321a380bf10Simaromclass _OutputRedirectingPdb(pdb.Pdb):
322a380bf10Simarom    """
323a380bf10Simarom    A specialized version of the python debugger that redirects stdout
324a380bf10Simarom    to a given stream when interacting with the user.  Stdout is *not*
325a380bf10Simarom    redirected when traced code is executed.
326a380bf10Simarom    """
327a380bf10Simarom    def __init__(self, out):
328a380bf10Simarom        self.__out = out
329a380bf10Simarom        pdb.Pdb.__init__(self)
330a380bf10Simarom
331a380bf10Simarom    def trace_dispatch(self, *args):
332a380bf10Simarom        # Redirect stdout to the given stream.
333a380bf10Simarom        save_stdout = sys.stdout
334a380bf10Simarom        sys.stdout = self.__out
335a380bf10Simarom        # Call Pdb's trace dispatch method.
336a380bf10Simarom        try:
337a380bf10Simarom            return pdb.Pdb.trace_dispatch(self, *args)
338a380bf10Simarom        finally:
339a380bf10Simarom            sys.stdout = save_stdout
340a380bf10Simarom
341a380bf10Simarom# [XX] Normalize with respect to os.path.pardir?
342a380bf10Simaromdef _module_relative_path(module, path):
343a380bf10Simarom    if not inspect.ismodule(module):
344a380bf10Simarom        raise TypeError('Expected a module: %r' % module)
345a380bf10Simarom    if path.startswith('/'):
346a380bf10Simarom        raise ValueError('Module-relative files may not have absolute paths')
347a380bf10Simarom
348a380bf10Simarom    # Find the base directory for the path.
349a380bf10Simarom    if hasattr(module, '__file__'):
350a380bf10Simarom        # A normal module/package
351a380bf10Simarom        basedir = os.path.split(module.__file__)[0]
352a380bf10Simarom    elif module.__name__ == '__main__':
353a380bf10Simarom        # An interactive session.
354a380bf10Simarom        if len(sys.argv)>0 and sys.argv[0] != '':
355a380bf10Simarom            basedir = os.path.split(sys.argv[0])[0]
356a380bf10Simarom        else:
357a380bf10Simarom            basedir = os.curdir
358a380bf10Simarom    else:
359a380bf10Simarom        # A module w/o __file__ (this includes builtins)
360a380bf10Simarom        raise ValueError("Can't resolve paths relative to the module " +
361a380bf10Simarom                         module + " (it has no __file__)")
362a380bf10Simarom
363a380bf10Simarom    # Combine the base directory and the path.
364a380bf10Simarom    return os.path.join(basedir, *(path.split('/')))
365a380bf10Simarom
366a380bf10Simarom######################################################################
367a380bf10Simarom## 2. Example & DocTest
368a380bf10Simarom######################################################################
369a380bf10Simarom## - An "example" is a <source, want> pair, where "source" is a
370a380bf10Simarom##   fragment of source code, and "want" is the expected output for
371a380bf10Simarom##   "source."  The Example class also includes information about
372a380bf10Simarom##   where the example was extracted from.
373a380bf10Simarom##
374a380bf10Simarom## - A "doctest" is a collection of examples, typically extracted from
375a380bf10Simarom##   a string (such as an object's docstring).  The DocTest class also
376a380bf10Simarom##   includes information about where the string was extracted from.
377a380bf10Simarom
378a380bf10Simaromclass Example:
379a380bf10Simarom    """
380a380bf10Simarom    A single doctest example, consisting of source code and expected
381a380bf10Simarom    output.  `Example` defines the following attributes:
382a380bf10Simarom
383a380bf10Simarom      - source: A single Python statement, always ending with a newline.
384a380bf10Simarom        The constructor adds a newline if needed.
385a380bf10Simarom
386a380bf10Simarom      - want: The expected output from running the source code (either
387a380bf10Simarom        from stdout, or a traceback in case of exception).  `want` ends
388a380bf10Simarom        with a newline unless it's empty, in which case it's an empty
389a380bf10Simarom        string.  The constructor adds a newline if needed.
390a380bf10Simarom
391a380bf10Simarom      - exc_msg: The exception message generated by the example, if
392a380bf10Simarom        the example is expected to generate an exception; or `None` if
393a380bf10Simarom        it is not expected to generate an exception.  This exception
394a380bf10Simarom        message is compared against the return value of
395a380bf10Simarom        `traceback.format_exception_only()`.  `exc_msg` ends with a
396a380bf10Simarom        newline unless it's `None`.  The constructor adds a newline
397a380bf10Simarom        if needed.
398a380bf10Simarom
399a380bf10Simarom      - lineno: The line number within the DocTest string containing
400a380bf10Simarom        this Example where the Example begins.  This line number is
401a380bf10Simarom        zero-based, with respect to the beginning of the DocTest.
402a380bf10Simarom
403a380bf10Simarom      - indent: The example's indentation in the DocTest string.
404a380bf10Simarom        I.e., the number of space characters that preceed the
405a380bf10Simarom        example's first prompt.
406a380bf10Simarom
407a380bf10Simarom      - options: A dictionary mapping from option flags to True or
408a380bf10Simarom        False, which is used to override default options for this
409a380bf10Simarom        example.  Any option flags not contained in this dictionary
410a380bf10Simarom        are left at their default value (as specified by the
411a380bf10Simarom        DocTestRunner's optionflags).  By default, no options are set.
412a380bf10Simarom    """
413a380bf10Simarom    def __init__(self, source, want, exc_msg=None, lineno=0, indent=0,
414a380bf10Simarom                 options=None):
415a380bf10Simarom        # Normalize inputs.
416a380bf10Simarom        if not source.endswith('\n'):
417a380bf10Simarom            source += '\n'
418a380bf10Simarom        if want and not want.endswith('\n'):
419a380bf10Simarom            want += '\n'
420a380bf10Simarom        if exc_msg is not None and not exc_msg.endswith('\n'):
421a380bf10Simarom            exc_msg += '\n'
422a380bf10Simarom        # Store properties.
423a380bf10Simarom        self.source = source
424a380bf10Simarom        self.want = want
425a380bf10Simarom        self.lineno = lineno
426a380bf10Simarom        self.indent = indent
427a380bf10Simarom        if options is None: options = {}
428a380bf10Simarom        self.options = options
429a380bf10Simarom        self.exc_msg = exc_msg
430a380bf10Simarom
431a380bf10Simaromclass DocTest:
432a380bf10Simarom    """
433a380bf10Simarom    A collection of doctest examples that should be run in a single
434a380bf10Simarom    namespace.  Each `DocTest` defines the following attributes:
435a380bf10Simarom
436a380bf10Simarom      - examples: the list of examples.
437a380bf10Simarom
438a380bf10Simarom      - globs: The namespace (aka globals) that the examples should
439a380bf10Simarom        be run in.
440a380bf10Simarom
441a380bf10Simarom      - name: A name identifying the DocTest (typically, the name of
442a380bf10Simarom        the object whose docstring this DocTest was extracted from).
443a380bf10Simarom
444a380bf10Simarom      - filename: The name of the file that this DocTest was extracted
445a380bf10Simarom        from, or `None` if the filename is unknown.
446a380bf10Simarom
447a380bf10Simarom      - lineno: The line number within filename where this DocTest
448a380bf10Simarom        begins, or `None` if the line number is unavailable.  This
449a380bf10Simarom        line number is zero-based, with respect to the beginning of
450a380bf10Simarom        the file.
451a380bf10Simarom
452a380bf10Simarom      - docstring: The string that the examples were extracted from,
453a380bf10Simarom        or `None` if the string is unavailable.
454a380bf10Simarom    """
455a380bf10Simarom    def __init__(self, examples, globs, name, filename, lineno, docstring):
456a380bf10Simarom        """
457a380bf10Simarom        Create a new DocTest containing the given examples.  The
458a380bf10Simarom        DocTest's globals are initialized with a copy of `globs`.
459a380bf10Simarom        """
460a380bf10Simarom        assert not isinstance(examples, str), \
461a380bf10Simarom               "DocTest no longer accepts str; use DocTestParser instead"
462a380bf10Simarom        self.examples = examples
463a380bf10Simarom        self.docstring = docstring
464a380bf10Simarom        self.globs = globs.copy()
465a380bf10Simarom        self.name = name
466a380bf10Simarom        self.filename = filename
467a380bf10Simarom        self.lineno = lineno
468a380bf10Simarom
469a380bf10Simarom    def __repr__(self):
470a380bf10Simarom        if len(self.examples) == 0:
471a380bf10Simarom            examples = 'no examples'
472a380bf10Simarom        elif len(self.examples) == 1:
473a380bf10Simarom            examples = '1 example'
474a380bf10Simarom        else:
475a380bf10Simarom            examples = '%d examples' % len(self.examples)
476a380bf10Simarom        return ('<DocTest %s from %s:%s (%s)>' %
477a380bf10Simarom                (self.name, self.filename, self.lineno, examples))
478a380bf10Simarom
479a380bf10Simarom
480a380bf10Simarom    # This lets us sort tests by name:
481a380bf10Simarom    def __cmp__(self, other):
482a380bf10Simarom        if not isinstance(other, DocTest):
483a380bf10Simarom            return -1
484a380bf10Simarom        return cmp((self.name, self.filename, self.lineno, id(self)),
485a380bf10Simarom                   (other.name, other.filename, other.lineno, id(other)))
486a380bf10Simarom
487a380bf10Simarom######################################################################
488a380bf10Simarom## 3. DocTestParser
489a380bf10Simarom######################################################################
490a380bf10Simarom
491a380bf10Simaromclass DocTestParser:
492a380bf10Simarom    """
493a380bf10Simarom    A class used to parse strings containing doctest examples.
494a380bf10Simarom    """
495a380bf10Simarom    # This regular expression is used to find doctest examples in a
496a380bf10Simarom    # string.  It defines three groups: `source` is the source code
497a380bf10Simarom    # (including leading indentation and prompts); `indent` is the
498a380bf10Simarom    # indentation of the first (PS1) line of the source code; and
499a380bf10Simarom    # `want` is the expected output (including leading indentation).
500a380bf10Simarom    _EXAMPLE_RE = re.compile(r'''
501a380bf10Simarom        # Source consists of a PS1 line followed by zero or more PS2 lines.
502a380bf10Simarom        (?P<source>
503a380bf10Simarom            (?:^(?P<indent> [ ]*) >>>    .*)    # PS1 line
504a380bf10Simarom            (?:\n           [ ]*  \.\.\. .*)*)  # PS2 lines
505a380bf10Simarom        \n?
506a380bf10Simarom        # Want consists of any non-blank lines that do not start with PS1.
507a380bf10Simarom        (?P<want> (?:(?![ ]*$)    # Not a blank line
508a380bf10Simarom                     (?![ ]*>>>)  # Not a line starting with PS1
509a380bf10Simarom                     .*$\n?       # But any other line
510a380bf10Simarom                  )*)
511a380bf10Simarom        ''', re.MULTILINE | re.VERBOSE)
512a380bf10Simarom
513a380bf10Simarom    # A regular expression for handling `want` strings that contain
514a380bf10Simarom    # expected exceptions.  It divides `want` into three pieces:
515a380bf10Simarom    #    - the traceback header line (`hdr`)
516a380bf10Simarom    #    - the traceback stack (`stack`)
517a380bf10Simarom    #    - the exception message (`msg`), as generated by
518a380bf10Simarom    #      traceback.format_exception_only()
519a380bf10Simarom    # `msg` may have multiple lines.  We assume/require that the
520a380bf10Simarom    # exception message is the first non-indented line starting with a word
521a380bf10Simarom    # character following the traceback header line.
522a380bf10Simarom    _EXCEPTION_RE = re.compile(r"""
523a380bf10Simarom        # Grab the traceback header.  Different versions of Python have
524a380bf10Simarom        # said different things on the first traceback line.
525a380bf10Simarom        ^(?P<hdr> Traceback\ \(
526a380bf10Simarom            (?: most\ recent\ call\ last
527a380bf10Simarom            |   innermost\ last
528a380bf10Simarom            ) \) :
529a380bf10Simarom        )
530a380bf10Simarom        \s* $                # toss trailing whitespace on the header.
531a380bf10Simarom        (?P<stack> .*?)      # don't blink: absorb stuff until...
532a380bf10Simarom        ^ (?P<msg> \w+ .*)   #     a line *starts* with alphanum.
533a380bf10Simarom        """, re.VERBOSE | re.MULTILINE | re.DOTALL)
534a380bf10Simarom
535a380bf10Simarom    # A callable returning a true value iff its argument is a blank line
536a380bf10Simarom    # or contains a single comment.
537a380bf10Simarom    _IS_BLANK_OR_COMMENT = re.compile(r'^[ ]*(#.*)?$').match
538a380bf10Simarom
539a380bf10Simarom    def parse(self, string, name='<string>'):
540a380bf10Simarom        """
541a380bf10Simarom        Divide the given string into examples and intervening text,
542a380bf10Simarom        and return them as a list of alternating Examples and strings.
543a380bf10Simarom        Line numbers for the Examples are 0-based.  The optional
544a380bf10Simarom        argument `name` is a name identifying this string, and is only
545a380bf10Simarom        used for error messages.
546a380bf10Simarom        """
547a380bf10Simarom        string = string.expandtabs()
548a380bf10Simarom        # If all lines begin with the same indentation, then strip it.
549a380bf10Simarom        min_indent = self._min_indent(string)
550a380bf10Simarom        if min_indent > 0:
551a380bf10Simarom            string = '\n'.join([l[min_indent:] for l in string.split('\n')])
552a380bf10Simarom
553a380bf10Simarom        output = []
554a380bf10Simarom        charno, lineno = 0, 0
555a380bf10Simarom        # Find all doctest examples in the string:
556a380bf10Simarom        for m in self._EXAMPLE_RE.finditer(string):
557a380bf10Simarom            # Add the pre-example text to `output`.
558a380bf10Simarom            output.append(string[charno:m.start()])
559a380bf10Simarom            # Update lineno (lines before this example)
560a380bf10Simarom            lineno += string.count('\n', charno, m.start())
561a380bf10Simarom            # Extract info from the regexp match.
562a380bf10Simarom            (source, options, want, exc_msg) = \
563a380bf10Simarom                     self._parse_example(m, name, lineno)
564a380bf10Simarom            # Create an Example, and add it to the list.
565a380bf10Simarom            if not self._IS_BLANK_OR_COMMENT(source):
566a380bf10Simarom                output.append( Example(source, want, exc_msg,
567a380bf10Simarom                                    lineno=lineno,
568a380bf10Simarom                                    indent=min_indent+len(m.group('indent')),
569a380bf10Simarom                                    options=options) )
570a380bf10Simarom            # Update lineno (lines inside this example)
571a380bf10Simarom            lineno += string.count('\n', m.start(), m.end())
572a380bf10Simarom            # Update charno.
573a380bf10Simarom            charno = m.end()
574a380bf10Simarom        # Add any remaining post-example text to `output`.
575a380bf10Simarom        output.append(string[charno:])
576a380bf10Simarom        return output
577a380bf10Simarom
578a380bf10Simarom    def get_doctest(self, string, globs, name, filename, lineno):
579a380bf10Simarom        """
580a380bf10Simarom        Extract all doctest examples from the given string, and
581a380bf10Simarom        collect them into a `DocTest` object.
582a380bf10Simarom
583a380bf10Simarom        `globs`, `name`, `filename`, and `lineno` are attributes for
584a380bf10Simarom        the new `DocTest` object.  See the documentation for `DocTest`
585a380bf10Simarom        for more information.
586a380bf10Simarom        """
587a380bf10Simarom        return DocTest(self.get_examples(string, name), globs,
588a380bf10Simarom                       name, filename, lineno, string)
589a380bf10Simarom
590a380bf10Simarom    def get_examples(self, string, name='<string>'):
591a380bf10Simarom        """
592a380bf10Simarom        Extract all doctest examples from the given string, and return
593a380bf10Simarom        them as a list of `Example` objects.  Line numbers are
594a380bf10Simarom        0-based, because it's most common in doctests that nothing
595a380bf10Simarom        interesting appears on the same line as opening triple-quote,
596a380bf10Simarom        and so the first interesting line is called \"line 1\" then.
597a380bf10Simarom
598a380bf10Simarom        The optional argument `name` is a name identifying this
599a380bf10Simarom        string, and is only used for error messages.
600a380bf10Simarom        """
601a380bf10Simarom        return [x for x in self.parse(string, name)
602a380bf10Simarom                if isinstance(x, Example)]
603a380bf10Simarom
604a380bf10Simarom    def _parse_example(self, m, name, lineno):
605a380bf10Simarom        """
606a380bf10Simarom        Given a regular expression match from `_EXAMPLE_RE` (`m`),
607a380bf10Simarom        return a pair `(source, want)`, where `source` is the matched
608a380bf10Simarom        example's source code (with prompts and indentation stripped);
609a380bf10Simarom        and `want` is the example's expected output (with indentation
610a380bf10Simarom        stripped).
611a380bf10Simarom
612a380bf10Simarom        `name` is the string's name, and `lineno` is the line number
613a380bf10Simarom        where the example starts; both are used for error messages.
614a380bf10Simarom        """
615a380bf10Simarom        # Get the example's indentation level.
616a380bf10Simarom        indent = len(m.group('indent'))
617a380bf10Simarom
618a380bf10Simarom        # Divide source into lines; check that they're properly
619a380bf10Simarom        # indented; and then strip their indentation & prompts.
620a380bf10Simarom        source_lines = m.group('source').split('\n')
621a380bf10Simarom        self._check_prompt_blank(source_lines, indent, name, lineno)
622a380bf10Simarom        self._check_prefix(source_lines[1:], ' '*indent + '.', name, lineno)
623a380bf10Simarom        source = '\n'.join([sl[indent+4:] for sl in source_lines])
624a380bf10Simarom
625a380bf10Simarom        # Divide want into lines; check that it's properly indented; and
626a380bf10Simarom        # then strip the indentation.  Spaces before the last newline should
627a380bf10Simarom        # be preserved, so plain rstrip() isn't good enough.
628a380bf10Simarom        want = m.group('want')
629a380bf10Simarom        want_lines = want.split('\n')
630a380bf10Simarom        if len(want_lines) > 1 and re.match(r' *$', want_lines[-1]):
631a380bf10Simarom            del want_lines[-1]  # forget final newline & spaces after it
632a380bf10Simarom        self._check_prefix(want_lines, ' '*indent, name,
633a380bf10Simarom                           lineno + len(source_lines))
634a380bf10Simarom        want = '\n'.join([wl[indent:] for wl in want_lines])
635a380bf10Simarom
636a380bf10Simarom        # If `want` contains a traceback message, then extract it.
637a380bf10Simarom        m = self._EXCEPTION_RE.match(want)
638a380bf10Simarom        if m:
639a380bf10Simarom            exc_msg = m.group('msg')
640a380bf10Simarom        else:
641a380bf10Simarom            exc_msg = None
642a380bf10Simarom
643a380bf10Simarom        # Extract options from the source.
644a380bf10Simarom        options = self._find_options(source, name, lineno)
645a380bf10Simarom
646a380bf10Simarom        return source, options, want, exc_msg
647a380bf10Simarom
648a380bf10Simarom    # This regular expression looks for option directives in the
649a380bf10Simarom    # source code of an example.  Option directives are comments
650a380bf10Simarom    # starting with "doctest:".  Warning: this may give false
651a380bf10Simarom    # positives for string-literals that contain the string
652a380bf10Simarom    # "#doctest:".  Eliminating these false positives would require
653a380bf10Simarom    # actually parsing the string; but we limit them by ignoring any
654a380bf10Simarom    # line containing "#doctest:" that is *followed* by a quote mark.
655a380bf10Simarom    _OPTION_DIRECTIVE_RE = re.compile(r'#\s*doctest:\s*([^\n\'"]*)$',
656a380bf10Simarom                                      re.MULTILINE)
657a380bf10Simarom
658a380bf10Simarom    def _find_options(self, source, name, lineno):
659a380bf10Simarom        """
660a380bf10Simarom        Return a dictionary containing option overrides extracted from
661a380bf10Simarom        option directives in the given source string.
662a380bf10Simarom
663a380bf10Simarom        `name` is the string's name, and `lineno` is the line number
664a380bf10Simarom        where the example starts; both are used for error messages.
665a380bf10Simarom        """
666a380bf10Simarom        options = {}
667a380bf10Simarom        # (note: with the current regexp, this will match at most once:)
668a380bf10Simarom        for m in self._OPTION_DIRECTIVE_RE.finditer(source):
669a380bf10Simarom            option_strings = m.group(1).replace(',', ' ').split()
670a380bf10Simarom            for option in option_strings:
671a380bf10Simarom                if (option[0] not in '+-' or
672a380bf10Simarom                    option[1:] not in OPTIONFLAGS_BY_NAME):
673a380bf10Simarom                    raise ValueError('line %r of the doctest for %s '
674a380bf10Simarom                                     'has an invalid option: %r' %
675a380bf10Simarom                                     (lineno+1, name, option))
676a380bf10Simarom                flag = OPTIONFLAGS_BY_NAME[option[1:]]
677a380bf10Simarom                options[flag] = (option[0] == '+')
678a380bf10Simarom        if options and self._IS_BLANK_OR_COMMENT(source):
679a380bf10Simarom            raise ValueError('line %r of the doctest for %s has an option '
680a380bf10Simarom                             'directive on a line with no example: %r' %
681a380bf10Simarom                             (lineno, name, source))
682a380bf10Simarom        return options
683a380bf10Simarom
684a380bf10Simarom    # This regular expression finds the indentation of every non-blank
685a380bf10Simarom    # line in a string.
686a380bf10Simarom    _INDENT_RE = re.compile('^([ ]*)(?=\S)', re.MULTILINE)
687a380bf10Simarom
688a380bf10Simarom    def _min_indent(self, s):
689a380bf10Simarom        "Return the minimum indentation of any non-blank line in `s`"
690a380bf10Simarom        indents = [len(indent) for indent in self._INDENT_RE.findall(s)]
691a380bf10Simarom        if len(indents) > 0:
692a380bf10Simarom            return min(indents)
693a380bf10Simarom        else:
694a380bf10Simarom            return 0
695a380bf10Simarom
696a380bf10Simarom    def _check_prompt_blank(self, lines, indent, name, lineno):
697a380bf10Simarom        """
698a380bf10Simarom        Given the lines of a source string (including prompts and
699a380bf10Simarom        leading indentation), check to make sure that every prompt is
700a380bf10Simarom        followed by a space character.  If any line is not followed by
701a380bf10Simarom        a space character, then raise ValueError.
702a380bf10Simarom        """
703a380bf10Simarom        for i, line in enumerate(lines):
704a380bf10Simarom            if len(line) >= indent+4 and line[indent+3] != ' ':
705a380bf10Simarom                raise ValueError('line %r of the docstring for %s '
706a380bf10Simarom                                 'lacks blank after %s: %r' %
707a380bf10Simarom                                 (lineno+i+1, name,
708a380bf10Simarom                                  line[indent:indent+3], line))
709a380bf10Simarom
710a380bf10Simarom    def _check_prefix(self, lines, prefix, name, lineno):
711a380bf10Simarom        """
712a380bf10Simarom        Check that every line in the given list starts with the given
713a380bf10Simarom        prefix; if any line does not, then raise a ValueError.
714a380bf10Simarom        """
715a380bf10Simarom        for i, line in enumerate(lines):
716a380bf10Simarom            if line and not line.startswith(prefix):
717a380bf10Simarom                raise ValueError('line %r of the docstring for %s has '
718a380bf10Simarom                                 'inconsistent leading whitespace: %r' %
719a380bf10Simarom                                 (lineno+i+1, name, line))
720a380bf10Simarom
721a380bf10Simarom
722a380bf10Simarom######################################################################
723a380bf10Simarom## 4. DocTest Finder
724a380bf10Simarom######################################################################
725a380bf10Simarom
726a380bf10Simaromclass DocTestFinder:
727a380bf10Simarom    """
728a380bf10Simarom    A class used to extract the DocTests that are relevant to a given
729a380bf10Simarom    object, from its docstring and the docstrings of its contained
730a380bf10Simarom    objects.  Doctests can currently be extracted from the following
731a380bf10Simarom    object types: modules, functions, classes, methods, staticmethods,
732a380bf10Simarom    classmethods, and properties.
733a380bf10Simarom    """
734a380bf10Simarom
735a380bf10Simarom    def __init__(self, verbose=False, parser=DocTestParser(),
736a380bf10Simarom                 recurse=True, _namefilter=None, exclude_empty=True):
737a380bf10Simarom        """
738a380bf10Simarom        Create a new doctest finder.
739a380bf10Simarom
740a380bf10Simarom        The optional argument `parser` specifies a class or
741a380bf10Simarom        function that should be used to create new DocTest objects (or
742a380bf10Simarom        objects that implement the same interface as DocTest).  The
743a380bf10Simarom        signature for this factory function should match the signature
744a380bf10Simarom        of the DocTest constructor.
745a380bf10Simarom
746a380bf10Simarom        If the optional argument `recurse` is false, then `find` will
747a380bf10Simarom        only examine the given object, and not any contained objects.
748a380bf10Simarom
749a380bf10Simarom        If the optional argument `exclude_empty` is false, then `find`
750a380bf10Simarom        will include tests for objects with empty docstrings.
751a380bf10Simarom        """
752a380bf10Simarom        self._parser = parser
753a380bf10Simarom        self._verbose = verbose
754a380bf10Simarom        self._recurse = recurse
755a380bf10Simarom        self._exclude_empty = exclude_empty
756a380bf10Simarom        # _namefilter is undocumented, and exists only for temporary backward-
757a380bf10Simarom        # compatibility support of testmod's deprecated isprivate mess.
758a380bf10Simarom        self._namefilter = _namefilter
759a380bf10Simarom
760a380bf10Simarom    def find(self, obj, name=None, module=None, globs=None,
761a380bf10Simarom             extraglobs=None):
762a380bf10Simarom        """
763a380bf10Simarom        Return a list of the DocTests that are defined by the given
764a380bf10Simarom        object's docstring, or by any of its contained objects'
765a380bf10Simarom        docstrings.
766a380bf10Simarom
767a380bf10Simarom        The optional parameter `module` is the module that contains
768a380bf10Simarom        the given object.  If the module is not specified or is None, then
769a380bf10Simarom        the test finder will attempt to automatically determine the
770a380bf10Simarom        correct module.  The object's module is used:
771a380bf10Simarom
772a380bf10Simarom            - As a default namespace, if `globs` is not specified.
773a380bf10Simarom            - To prevent the DocTestFinder from extracting DocTests
774a380bf10Simarom              from objects that are imported from other modules.
775a380bf10Simarom            - To find the name of the file containing the object.
776a380bf10Simarom            - To help find the line number of the object within its
777a380bf10Simarom              file.
778a380bf10Simarom
779a380bf10Simarom        Contained objects whose module does not match `module` are ignored.
780a380bf10Simarom
781a380bf10Simarom        If `module` is False, no attempt to find the module will be made.
782a380bf10Simarom        This is obscure, of use mostly in tests:  if `module` is False, or
783a380bf10Simarom        is None but cannot be found automatically, then all objects are
784a380bf10Simarom        considered to belong to the (non-existent) module, so all contained
785a380bf10Simarom        objects will (recursively) be searched for doctests.
786a380bf10Simarom
787a380bf10Simarom        The globals for each DocTest is formed by combining `globs`
788a380bf10Simarom        and `extraglobs` (bindings in `extraglobs` override bindings
789a380bf10Simarom        in `globs`).  A new copy of the globals dictionary is created
790a380bf10Simarom        for each DocTest.  If `globs` is not specified, then it
791a380bf10Simarom        defaults to the module's `__dict__`, if specified, or {}
792a380bf10Simarom        otherwise.  If `extraglobs` is not specified, then it defaults
793a380bf10Simarom        to {}.
794a380bf10Simarom
795a380bf10Simarom        """
796a380bf10Simarom        # If name was not specified, then extract it from the object.
797a380bf10Simarom        if name is None:
798a380bf10Simarom            name = getattr(obj, '__name__', None)
799a380bf10Simarom            if name is None:
800a380bf10Simarom                raise ValueError("DocTestFinder.find: name must be given "
801a380bf10Simarom                        "when obj.__name__ doesn't exist: %r" %
802a380bf10Simarom                                 (type(obj),))
803a380bf10Simarom
804a380bf10Simarom        # Find the module that contains the given object (if obj is
805a380bf10Simarom        # a module, then module=obj.).  Note: this may fail, in which
806a380bf10Simarom        # case module will be None.
807a380bf10Simarom        if module is False:
808a380bf10Simarom            module = None
809a380bf10Simarom        elif module is None:
810a380bf10Simarom            module = inspect.getmodule(obj)
811a380bf10Simarom
812a380bf10Simarom        # Read the module's source code.  This is used by
813a380bf10Simarom        # DocTestFinder._find_lineno to find the line number for a
814a380bf10Simarom        # given object's docstring.
815a380bf10Simarom        try:
816a380bf10Simarom            file = inspect.getsourcefile(obj) or inspect.getfile(obj)
817a380bf10Simarom            source_lines = linecache.getlines(file)
818a380bf10Simarom            if not source_lines:
819a380bf10Simarom                source_lines = None
820a380bf10Simarom        except TypeError:
821a380bf10Simarom            source_lines = None
822a380bf10Simarom
823a380bf10Simarom        # Initialize globals, and merge in extraglobs.
824a380bf10Simarom        if globs is None:
825a380bf10Simarom            if module is None:
826a380bf10Simarom                globs = {}
827a380bf10Simarom            else:
828a380bf10Simarom                globs = module.__dict__.copy()
829a380bf10Simarom        else:
830a380bf10Simarom            globs = globs.copy()
831a380bf10Simarom        if extraglobs is not None:
832a380bf10Simarom            globs.update(extraglobs)
833a380bf10Simarom
834a380bf10Simarom        # Recursively expore `obj`, extracting DocTests.
835a380bf10Simarom        tests = []
836a380bf10Simarom        self._find(tests, obj, name, module, source_lines, globs, {})
837a380bf10Simarom        # Sort the tests by alpha order of names, for consistency in
838a380bf10Simarom        # verbose-mode output.  This was a feature of doctest in Pythons
839a380bf10Simarom        # <= 2.3 that got lost by accident in 2.4.  It was repaired in
840a380bf10Simarom        # 2.4.4 and 2.5.
841a380bf10Simarom        tests.sort()
842a380bf10Simarom        return tests
843a380bf10Simarom
844a380bf10Simarom    def _filter(self, obj, prefix, base):
845a380bf10Simarom        """
846a380bf10Simarom        Return true if the given object should not be examined.
847a380bf10Simarom        """
848a380bf10Simarom        return (self._namefilter is not None and
849a380bf10Simarom                self._namefilter(prefix, base))
850a380bf10Simarom
851a380bf10Simarom    def _from_module(self, module, object):
852a380bf10Simarom        """
853a380bf10Simarom        Return true if the given object is defined in the given
854a380bf10Simarom        module.
855a380bf10Simarom        """
856a380bf10Simarom        if module is None:
857a380bf10Simarom            return True
858a380bf10Simarom        elif inspect.isfunction(object):
859a380bf10Simarom            return module.__dict__ is object.__globals__
860a380bf10Simarom        elif inspect.isclass(object):
861a380bf10Simarom            # Some jython classes don't set __module__
862a380bf10Simarom            return module.__name__ == getattr(object, '__module__', None)
863a380bf10Simarom        elif inspect.getmodule(object) is not None:
864a380bf10Simarom            return module is inspect.getmodule(object)
865a380bf10Simarom        elif hasattr(object, '__module__'):
866a380bf10Simarom            return module.__name__ == object.__module__
867a380bf10Simarom        elif isinstance(object, property):
868a380bf10Simarom            return True # [XX] no way not be sure.
869a380bf10Simarom        else:
870a380bf10Simarom            raise ValueError("object must be a class or function")
871a380bf10Simarom
872a380bf10Simarom    def _find(self, tests, obj, name, module, source_lines, globs, seen):
873a380bf10Simarom        """
874a380bf10Simarom        Find tests for the given object and any contained objects, and
875a380bf10Simarom        add them to `tests`.
876a380bf10Simarom        """
877a380bf10Simarom        if self._verbose:
878a380bf10Simarom            print('Finding tests in %s' % name)
879a380bf10Simarom
880a380bf10Simarom        # If we've already processed this object, then ignore it.
881a380bf10Simarom        if id(obj) in seen:
882a380bf10Simarom            return
883a380bf10Simarom        seen[id(obj)] = 1
884a380bf10Simarom
885a380bf10Simarom        # Find a test for this object, and add it to the list of tests.
886a380bf10Simarom        test = self._get_test(obj, name, module, globs, source_lines)
887a380bf10Simarom        if test is not None:
888a380bf10Simarom            tests.append(test)
889a380bf10Simarom
890a380bf10Simarom        # Look for tests in a module's contained objects.
891a380bf10Simarom        if inspect.ismodule(obj) and self._recurse:
892a380bf10Simarom            for valname, val in list(obj.__dict__.items()):
893a380bf10Simarom                # Check if this contained object should be ignored.
894a380bf10Simarom                if self._filter(val, name, valname):
895a380bf10Simarom                    continue
896a380bf10Simarom                valname = '%s.%s' % (name, valname)
897a380bf10Simarom                # Recurse to functions & classes.
898a380bf10Simarom                if ((inspect.isfunction(val) or inspect.isclass(val)) and
899a380bf10Simarom                    self._from_module(module, val)):
900a380bf10Simarom                    self._find(tests, val, valname, module, source_lines,
901a380bf10Simarom                               globs, seen)
902a380bf10Simarom
903a380bf10Simarom        # Look for tests in a module's __test__ dictionary.
904a380bf10Simarom        if inspect.ismodule(obj) and self._recurse:
905a380bf10Simarom            for valname, val in list(getattr(obj, '__test__', {}).items()):
906a380bf10Simarom                if not isinstance(valname, str):
907a380bf10Simarom                    raise ValueError("DocTestFinder.find: __test__ keys "
908a380bf10Simarom                                     "must be strings: %r" %
909a380bf10Simarom                                     (type(valname),))
910a380bf10Simarom                if not (inspect.isfunction(val) or inspect.isclass(val) or
911a380bf10Simarom                        inspect.ismethod(val) or inspect.ismodule(val) or
912a380bf10Simarom                        isinstance(val, str)):
913a380bf10Simarom                    raise ValueError("DocTestFinder.find: __test__ values "
914a380bf10Simarom                                     "must be strings, functions, methods, "
915a380bf10Simarom                                     "classes, or modules: %r" %
916a380bf10Simarom                                     (type(val),))
917a380bf10Simarom                valname = '%s.__test__.%s' % (name, valname)
918a380bf10Simarom                self._find(tests, val, valname, module, source_lines,
919a380bf10Simarom                           globs, seen)
920a380bf10Simarom
921a380bf10Simarom        # Look for tests in a class's contained objects.
922a380bf10Simarom        if inspect.isclass(obj) and self._recurse:
923a380bf10Simarom            for valname, val in list(obj.__dict__.items()):
924a380bf10Simarom                # Check if this contained object should be ignored.
925a380bf10Simarom                if self._filter(val, name, valname):
926a380bf10Simarom                    continue
927a380bf10Simarom                # Special handling for staticmethod/classmethod.
928a380bf10Simarom                if isinstance(val, staticmethod):
929a380bf10Simarom                    val = getattr(obj, valname)
930a380bf10Simarom                if isinstance(val, classmethod):
931a380bf10Simarom                    val = getattr(obj, valname).__func__
932a380bf10Simarom
933a380bf10Simarom                # Recurse to methods, properties, and nested classes.
934a380bf10Simarom                if ((inspect.isfunction(val) or inspect.isclass(val) or
935a380bf10Simarom                      isinstance(val, property)) and
936a380bf10Simarom                      self._from_module(module, val)):
937a380bf10Simarom                    valname = '%s.%s' % (name, valname)
938a380bf10Simarom                    self._find(tests, val, valname, module, source_lines,
939a380bf10Simarom                               globs, seen)
940a380bf10Simarom
941a380bf10Simarom    def _get_test(self, obj, name, module, globs, source_lines):
942a380bf10Simarom        """
943a380bf10Simarom        Return a DocTest for the given object, if it defines a docstring;
944a380bf10Simarom        otherwise, return None.
945a380bf10Simarom        """
946a380bf10Simarom        # Extract the object's docstring.  If it doesn't have one,
947a380bf10Simarom        # then return None (no test for this object).
948a380bf10Simarom        if isinstance(obj, str):
949a380bf10Simarom            docstring = obj
950a380bf10Simarom        else:
951a380bf10Simarom            try:
952a380bf10Simarom                if obj.__doc__ is None:
953a380bf10Simarom                    docstring = ''
954a380bf10Simarom                else:
955a380bf10Simarom                    docstring = obj.__doc__
956a380bf10Simarom                    if not isinstance(docstring, str):
957a380bf10Simarom                        docstring = str(docstring)
958a380bf10Simarom            except (TypeError, AttributeError):
959a380bf10Simarom                docstring = ''
960a380bf10Simarom
961a380bf10Simarom        # Find the docstring's location in the file.
962a380bf10Simarom        lineno = self._find_lineno(obj, source_lines)
963a380bf10Simarom
964a380bf10Simarom        # Don't bother if the docstring is empty.
965a380bf10Simarom        if self._exclude_empty and not docstring:
966a380bf10Simarom            return None
967a380bf10Simarom
968a380bf10Simarom        # Return a DocTest for this object.
969a380bf10Simarom        if module is None:
970a380bf10Simarom            filename = None
971a380bf10Simarom        else:
972a380bf10Simarom            filename = getattr(module, '__file__', module.__name__)
973a380bf10Simarom            if filename[-4:] in (".pyc", ".pyo"):
974a380bf10Simarom                filename = filename[:-1]
975a380bf10Simarom            elif sys.platform.startswith('java') and \
976a380bf10Simarom                    filename.endswith('$py.class'):
977a380bf10Simarom                filename = '%s.py' % filename[:-9]
978a380bf10Simarom        return self._parser.get_doctest(docstring, globs, name,
979a380bf10Simarom                                        filename, lineno)
980a380bf10Simarom
981a380bf10Simarom    def _find_lineno(self, obj, source_lines):
982a380bf10Simarom        """
983a380bf10Simarom        Return a line number of the given object's docstring.  Note:
984a380bf10Simarom        this method assumes that the object has a docstring.
985a380bf10Simarom        """
986a380bf10Simarom        lineno = None
987a380bf10Simarom
988a380bf10Simarom        # Find the line number for modules.
989a380bf10Simarom        if inspect.ismodule(obj):
990a380bf10Simarom            lineno = 0
991a380bf10Simarom
992a380bf10Simarom        # Find the line number for classes.
993a380bf10Simarom        # Note: this could be fooled if a class is defined multiple
994a380bf10Simarom        # times in a single file.
995a380bf10Simarom        if inspect.isclass(obj):
996a380bf10Simarom            if source_lines is None:
997a380bf10Simarom                return None
998a380bf10Simarom            pat = re.compile(r'^\s*class\s*%s\b' %
999a380bf10Simarom                             getattr(obj, '__name__', '-'))
1000a380bf10Simarom            for i, line in enumerate(source_lines):
1001a380bf10Simarom                if pat.match(line):
1002a380bf10Simarom                    lineno = i
1003a380bf10Simarom                    break
1004a380bf10Simarom
1005a380bf10Simarom        # Find the line number for functions & methods.
1006a380bf10Simarom        if inspect.ismethod(obj): obj = obj.__func__
1007a380bf10Simarom        if inspect.isfunction(obj): obj = obj.__code__
1008a380bf10Simarom        if inspect.istraceback(obj): obj = obj.tb_frame
1009a380bf10Simarom        if inspect.isframe(obj): obj = obj.f_code
1010a380bf10Simarom        if inspect.iscode(obj):
1011a380bf10Simarom            lineno = getattr(obj, 'co_firstlineno', None)-1
1012a380bf10Simarom
1013a380bf10Simarom        # Find the line number where the docstring starts.  Assume
1014a380bf10Simarom        # that it's the first line that begins with a quote mark.
1015a380bf10Simarom        # Note: this could be fooled by a multiline function
1016a380bf10Simarom        # signature, where a continuation line begins with a quote
1017a380bf10Simarom        # mark.
1018a380bf10Simarom        if lineno is not None:
1019a380bf10Simarom            if source_lines is None:
1020a380bf10Simarom                return lineno+1
1021a380bf10Simarom            pat = re.compile('(^|.*:)\s*\w*("|\')')
1022a380bf10Simarom            for lineno in range(lineno, len(source_lines)):
1023a380bf10Simarom                if pat.match(source_lines[lineno]):
1024a380bf10Simarom                    return lineno
1025a380bf10Simarom
1026a380bf10Simarom        # We couldn't find the line number.
1027a380bf10Simarom        return None
1028a380bf10Simarom
1029a380bf10Simarom######################################################################
1030a380bf10Simarom## 5. DocTest Runner
1031a380bf10Simarom######################################################################
1032a380bf10Simarom
1033a380bf10Simaromclass DocTestRunner:
1034a380bf10Simarom    # This divider string is used to separate failure messages, and to
1035a380bf10Simarom    # separate sections of the summary.
1036a380bf10Simarom    DIVIDER = "*" * 70
1037a380bf10Simarom
1038a380bf10Simarom    def __init__(self, checker=None, verbose=None, optionflags=0):
1039a380bf10Simarom        """
1040a380bf10Simarom        Create a new test runner.
1041a380bf10Simarom
1042a380bf10Simarom        Optional keyword arg `checker` is the `OutputChecker` that
1043a380bf10Simarom        should be used to compare the expected outputs and actual
1044a380bf10Simarom        outputs of doctest examples.
1045a380bf10Simarom
1046a380bf10Simarom        Optional keyword arg 'verbose' prints lots of stuff if true,
1047a380bf10Simarom        only failures if false; by default, it's true iff '-v' is in
1048a380bf10Simarom        sys.argv.
1049a380bf10Simarom
1050a380bf10Simarom        Optional argument `optionflags` can be used to control how the
1051a380bf10Simarom        test runner compares expected output to actual output, and how
1052a380bf10Simarom        it displays failures.  See the documentation for `testmod` for
1053a380bf10Simarom        more information.
1054a380bf10Simarom        """
1055a380bf10Simarom        self._checker = checker or OutputChecker()
1056a380bf10Simarom        if verbose is None:
1057a380bf10Simarom            verbose = '-v' in sys.argv
1058a380bf10Simarom        self._verbose = verbose
1059a380bf10Simarom        self.optionflags = optionflags
1060a380bf10Simarom        self.original_optionflags = optionflags
1061a380bf10Simarom
1062a380bf10Simarom        # Keep track of the examples we've run.
1063a380bf10Simarom        self.tries = 0
1064a380bf10Simarom        self.failures = 0
1065a380bf10Simarom        self._name2ft = {}
1066a380bf10Simarom
1067a380bf10Simarom        # Create a fake output target for capturing doctest output.
1068a380bf10Simarom        self._fakeout = _SpoofOut()
1069a380bf10Simarom
1070a380bf10Simarom    #/////////////////////////////////////////////////////////////////
1071a380bf10Simarom    # Reporting methods
1072a380bf10Simarom    #/////////////////////////////////////////////////////////////////
1073a380bf10Simarom
1074a380bf10Simarom    def report_start(self, out, test, example):
1075a380bf10Simarom        """
1076a380bf10Simarom        Report that the test runner is about to process the given
1077a380bf10Simarom        example.  (Only displays a message if verbose=True)
1078a380bf10Simarom        """
1079a380bf10Simarom        if self._verbose:
1080a380bf10Simarom            if example.want:
1081a380bf10Simarom                out('Trying:\n' + _indent(example.source) +
1082a380bf10Simarom                    'Expecting:\n' + _indent(example.want))
1083a380bf10Simarom            else:
1084a380bf10Simarom                out('Trying:\n' + _indent(example.source) +
1085a380bf10Simarom                    'Expecting nothing\n')
1086a380bf10Simarom
1087a380bf10Simarom    def report_success(self, out, test, example, got):
1088a380bf10Simarom        """
1089a380bf10Simarom        Report that the given example ran successfully.  (Only
1090a380bf10Simarom        displays a message if verbose=True)
1091a380bf10Simarom        """
1092a380bf10Simarom        if self._verbose:
1093a380bf10Simarom            out("ok\n")
1094a380bf10Simarom
1095a380bf10Simarom    def report_failure(self, out, test, example, got):
1096a380bf10Simarom        """
1097a380bf10Simarom        Report that the given example failed.
1098a380bf10Simarom        """
1099a380bf10Simarom        out(self._failure_header(test, example) +
1100a380bf10Simarom            self._checker.output_difference(example, got, self.optionflags))
1101a380bf10Simarom
1102a380bf10Simarom    def report_unexpected_exception(self, out, test, example, exc_info):
1103a380bf10Simarom        """
1104a380bf10Simarom        Report that the given example raised an unexpected exception.
1105a380bf10Simarom        """
1106a380bf10Simarom        out(self._failure_header(test, example) +
1107a380bf10Simarom            'Exception raised:\n' + _indent(_exception_traceback(exc_info)))
1108a380bf10Simarom
1109a380bf10Simarom    def _failure_header(self, test, example):
1110a380bf10Simarom        out = [self.DIVIDER]
1111a380bf10Simarom        if test.filename:
1112a380bf10Simarom            if test.lineno is not None and example.lineno is not None:
1113a380bf10Simarom                lineno = test.lineno + example.lineno + 1
1114a380bf10Simarom            else:
1115a380bf10Simarom                lineno = '?'
1116a380bf10Simarom            out.append('File "%s", line %s, in %s' %
1117a380bf10Simarom                       (test.filename, lineno, test.name))
1118a380bf10Simarom        else:
1119a380bf10Simarom            out.append('Line %s, in %s' % (example.lineno+1, test.name))
1120a380bf10Simarom        out.append('Failed example:')
1121a380bf10Simarom        source = example.source
1122a380bf10Simarom        out.append(_indent(source))
1123a380bf10Simarom        return '\n'.join(out)
1124a380bf10Simarom
1125a380bf10Simarom    #/////////////////////////////////////////////////////////////////
1126a380bf10Simarom    # DocTest Running
1127a380bf10Simarom    #/////////////////////////////////////////////////////////////////
1128a380bf10Simarom
1129a380bf10Simarom    def __run(self, test, compileflags, out):
1130a380bf10Simarom        """
1131a380bf10Simarom        Run the examples in `test`.  Write the outcome of each example
1132a380bf10Simarom        with one of the `DocTestRunner.report_*` methods, using the
1133a380bf10Simarom        writer function `out`.  `compileflags` is the set of compiler
1134a380bf10Simarom        flags that should be used to execute examples.  Return a tuple
1135a380bf10Simarom        `(f, t)`, where `t` is the number of examples tried, and `f`
1136a380bf10Simarom        is the number of examples that failed.  The examples are run
1137a380bf10Simarom        in the namespace `test.globs`.
1138a380bf10Simarom        """
1139a380bf10Simarom        # Keep track of the number of failures and tries.
1140a380bf10Simarom        failures = tries = 0
1141a380bf10Simarom
1142a380bf10Simarom        # Save the option flags (since option directives can be used
1143a380bf10Simarom        # to modify them).
1144a380bf10Simarom        original_optionflags = self.optionflags
1145a380bf10Simarom
1146a380bf10Simarom        SUCCESS, FAILURE, BOOM = list(range(3)) # `outcome` state
1147a380bf10Simarom
1148a380bf10Simarom        check = self._checker.check_output
1149a380bf10Simarom
1150a380bf10Simarom        # Process each example.
1151a380bf10Simarom        for examplenum, example in enumerate(test.examples):
1152a380bf10Simarom
1153a380bf10Simarom            # If REPORT_ONLY_FIRST_FAILURE is set, then supress
1154a380bf10Simarom            # reporting after the first failure.
1155a380bf10Simarom            quiet = (self.optionflags & REPORT_ONLY_FIRST_FAILURE and
1156a380bf10Simarom                     failures > 0)
1157a380bf10Simarom
1158a380bf10Simarom            # Merge in the example's options.
1159a380bf10Simarom            self.optionflags = original_optionflags
1160a380bf10Simarom            if example.options:
1161a380bf10Simarom                for (optionflag, val) in list(example.options.items()):
1162a380bf10Simarom                    if val:
1163a380bf10Simarom                        self.optionflags |= optionflag
1164a380bf10Simarom                    else:
1165a380bf10Simarom                        self.optionflags &= ~optionflag
1166a380bf10Simarom
1167a380bf10Simarom            # Record that we started this example.
1168a380bf10Simarom            tries += 1
1169a380bf10Simarom            if not quiet:
1170a380bf10Simarom                self.report_start(out, test, example)
1171a380bf10Simarom
1172a380bf10Simarom            # Use a special filename for compile(), so we can retrieve
1173a380bf10Simarom            # the source code during interactive debugging (see
1174a380bf10Simarom            # __patched_linecache_getlines).
1175a380bf10Simarom            filename = '<doctest %s[%d]>' % (test.name, examplenum)
1176a380bf10Simarom
1177a380bf10Simarom            # Run the example in the given context (globs), and record
1178a380bf10Simarom            # any exception that gets raised.  (But don't intercept
1179a380bf10Simarom            # keyboard interrupts.)
1180a380bf10Simarom            try:
1181a380bf10Simarom                # Don't blink!  This is where the user's code gets run.
1182a380bf10Simarom                exec(compile(example.source, filename, "single",
1183a380bf10Simarom                             compileflags, 1), test.globs)
1184a380bf10Simarom                self.debugger.set_continue() # ==== Example Finished ====
1185a380bf10Simarom                exception = None
1186a380bf10Simarom            except KeyboardInterrupt:
1187a380bf10Simarom                raise
1188a380bf10Simarom            except:
1189a380bf10Simarom                exception = sys.exc_info()
1190a380bf10Simarom                self.debugger.set_continue() # ==== Example Finished ====
1191a380bf10Simarom
1192a380bf10Simarom            got = self._fakeout.getvalue()  # the actual output
1193a380bf10Simarom            self._fakeout.truncate(0)
1194a380bf10Simarom            outcome = FAILURE   # guilty until proved innocent or insane
1195a380bf10Simarom
1196a380bf10Simarom            # If the example executed without raising any exceptions,
1197a380bf10Simarom            # verify its output.
1198a380bf10Simarom            if exception is None:
1199a380bf10Simarom                if check(example.want, got, self.optionflags):
1200a380bf10Simarom                    outcome = SUCCESS
1201a380bf10Simarom
1202a380bf10Simarom            # The example raised an exception:  check if it was expected.
1203a380bf10Simarom            else:
1204a380bf10Simarom                exc_info = sys.exc_info()
1205a380bf10Simarom                exc_msg = traceback.format_exception_only(*exc_info[:2])[-1]
1206a380bf10Simarom                if not quiet:
1207a380bf10Simarom                    got += _exception_traceback(exc_info)
1208a380bf10Simarom
1209a380bf10Simarom                # If `example.exc_msg` is None, then we weren't expecting
1210a380bf10Simarom                # an exception.
1211a380bf10Simarom                if example.exc_msg is None:
1212a380bf10Simarom                    outcome = BOOM
1213a380bf10Simarom
1214a380bf10Simarom                # We expected an exception:  see whether it matches.
1215a380bf10Simarom                elif check(example.exc_msg, exc_msg, self.optionflags):
1216a380bf10Simarom                    outcome = SUCCESS
1217a380bf10Simarom
1218a380bf10Simarom                # Another chance if they didn't care about the detail.
1219a380bf10Simarom                elif self.optionflags & IGNORE_EXCEPTION_DETAIL:
1220a380bf10Simarom                    m1 = re.match(r'[^:]*:', example.exc_msg)
1221a380bf10Simarom                    m2 = re.match(r'[^:]*:', exc_msg)
1222a380bf10Simarom                    if m1 and m2 and check(m1.group(0), m2.group(0),
1223a380bf10Simarom                                           self.optionflags):
1224a380bf10Simarom                        outcome = SUCCESS
1225a380bf10Simarom
1226a380bf10Simarom            # Report the outcome.
1227a380bf10Simarom            if outcome is SUCCESS:
1228a380bf10Simarom                if not quiet:
1229a380bf10Simarom                    self.report_success(out, test, example, got)
1230a380bf10Simarom            elif outcome is FAILURE:
1231a380bf10Simarom                if not quiet:
1232a380bf10Simarom                    self.report_failure(out, test, example, got)
1233a380bf10Simarom                failures += 1
1234a380bf10Simarom            elif outcome is BOOM:
1235a380bf10Simarom                if not quiet:
1236a380bf10Simarom                    self.report_unexpected_exception(out, test, example,
1237a380bf10Simarom                                                     exc_info)
1238a380bf10Simarom                failures += 1
1239a380bf10Simarom            else:
1240a380bf10Simarom                assert False, ("unknown outcome", outcome)
1241a380bf10Simarom
1242a380bf10Simarom        # Restore the option flags (in case they were modified)
1243a380bf10Simarom        self.optionflags = original_optionflags
1244a380bf10Simarom
1245a380bf10Simarom        # Record and return the number of failures and tries.
1246a380bf10Simarom        self.__record_outcome(test, failures, tries)
1247a380bf10Simarom        return failures, tries
1248a380bf10Simarom
1249a380bf10Simarom    def __record_outcome(self, test, f, t):
1250a380bf10Simarom        """
1251a380bf10Simarom        Record the fact that the given DocTest (`test`) generated `f`
1252a380bf10Simarom        failures out of `t` tried examples.
1253a380bf10Simarom        """
1254a380bf10Simarom        f2, t2 = self._name2ft.get(test.name, (0,0))
1255a380bf10Simarom        self._name2ft[test.name] = (f+f2, t+t2)
1256a380bf10Simarom        self.failures += f
1257a380bf10Simarom        self.tries += t
1258a380bf10Simarom
1259a380bf10Simarom    __LINECACHE_FILENAME_RE = re.compile(r'<doctest '
1260a380bf10Simarom                                         r'(?P<name>[\w\.]+)'
1261a380bf10Simarom                                         r'\[(?P<examplenum>\d+)\]>$')
1262a380bf10Simarom    def __patched_linecache_getlines(self, filename):
1263a380bf10Simarom        m = self.__LINECACHE_FILENAME_RE.match(filename)
1264a380bf10Simarom        if m and m.group('name') == self.test.name:
1265a380bf10Simarom            example = self.test.examples[int(m.group('examplenum'))]
1266a380bf10Simarom            return example.source.splitlines(True)
1267a380bf10Simarom        else:
1268a380bf10Simarom            return self.save_linecache_getlines(filename)
1269a380bf10Simarom
1270a380bf10Simarom    def run(self, test, compileflags=None, out=None, clear_globs=True):
1271a380bf10Simarom        """
1272a380bf10Simarom        Run the examples in `test`, and display the results using the
1273a380bf10Simarom        writer function `out`.
1274a380bf10Simarom
1275a380bf10Simarom        The examples are run in the namespace `test.globs`.  If
1276a380bf10Simarom        `clear_globs` is true (the default), then this namespace will
1277a380bf10Simarom        be cleared after the test runs, to help with garbage
1278a380bf10Simarom        collection.  If you would like to examine the namespace after
1279a380bf10Simarom        the test completes, then use `clear_globs=False`.
1280a380bf10Simarom
1281a380bf10Simarom        `compileflags` gives the set of flags that should be used by
1282a380bf10Simarom        the Python compiler when running the examples.  If not
1283a380bf10Simarom        specified, then it will default to the set of future-import
1284a380bf10Simarom        flags that apply to `globs`.
1285a380bf10Simarom
1286a380bf10Simarom        The output of each example is checked using
1287a380bf10Simarom        `DocTestRunner.check_output`, and the results are formatted by
1288a380bf10Simarom        the `DocTestRunner.report_*` methods.
1289a380bf10Simarom        """
1290a380bf10Simarom        self.test = test
1291a380bf10Simarom
1292a380bf10Simarom        if compileflags is None:
1293a380bf10Simarom            compileflags = _extract_future_flags(test.globs)
1294a380bf10Simarom
1295a380bf10Simarom        save_stdout = sys.stdout
1296a380bf10Simarom        if out is None:
1297a380bf10Simarom            out = save_stdout.write
1298a380bf10Simarom        sys.stdout = self._fakeout
1299a380bf10Simarom
1300a380bf10Simarom        # Patch pdb.set_trace to restore sys.stdout during interactive
1301a380bf10Simarom        # debugging (so it's not still redirected to self._fakeout).
1302a380bf10Simarom        # Note that the interactive output will go to *our*
1303a380bf10Simarom        # save_stdout, even if that's not the real sys.stdout; this
1304a380bf10Simarom        # allows us to write test cases for the set_trace behavior.
1305a380bf10Simarom        save_set_trace = pdb.set_trace
1306a380bf10Simarom        self.debugger = _OutputRedirectingPdb(save_stdout)
1307a380bf10Simarom        self.debugger.reset()
1308a380bf10Simarom        pdb.set_trace = self.debugger.set_trace
1309a380bf10Simarom
1310a380bf10Simarom        # Patch linecache.getlines, so we can see the example's source
1311a380bf10Simarom        # when we're inside the debugger.
1312a380bf10Simarom        self.save_linecache_getlines = linecache.getlines
1313a380bf10Simarom        linecache.getlines = self.__patched_linecache_getlines
1314a380bf10Simarom
1315a380bf10Simarom        try:
1316a380bf10Simarom            return self.__run(test, compileflags, out)
1317a380bf10Simarom        finally:
1318a380bf10Simarom            sys.stdout = save_stdout
1319a380bf10Simarom            pdb.set_trace = save_set_trace
1320a380bf10Simarom            linecache.getlines = self.save_linecache_getlines
1321a380bf10Simarom            if clear_globs:
1322a380bf10Simarom                test.globs.clear()
1323a380bf10Simarom
1324a380bf10Simarom    #/////////////////////////////////////////////////////////////////
1325a380bf10Simarom    # Summarization
1326a380bf10Simarom    #/////////////////////////////////////////////////////////////////
1327a380bf10Simarom    def summarize(self, verbose=None):
1328a380bf10Simarom        """
1329a380bf10Simarom        Print a summary of all the test cases that have been run by
1330a380bf10Simarom        this DocTestRunner, and return a tuple `(f, t)`, where `f` is
1331a380bf10Simarom        the total number of failed examples, and `t` is the total
1332a380bf10Simarom        number of tried examples.
1333a380bf10Simarom
1334a380bf10Simarom        The optional `verbose` argument controls how detailed the
1335a380bf10Simarom        summary is.  If the verbosity is not specified, then the
1336a380bf10Simarom        DocTestRunner's verbosity is used.
1337a380bf10Simarom        """
1338a380bf10Simarom        if verbose is None:
1339a380bf10Simarom            verbose = self._verbose
1340a380bf10Simarom        notests = []
1341a380bf10Simarom        passed = []
1342a380bf10Simarom        failed = []
1343a380bf10Simarom        totalt = totalf = 0
1344a380bf10Simarom        for x in list(self._name2ft.items()):
1345a380bf10Simarom            name, (f, t) = x
1346a380bf10Simarom            assert f <= t
1347a380bf10Simarom            totalt += t
1348a380bf10Simarom            totalf += f
1349a380bf10Simarom            if t == 0:
1350a380bf10Simarom                notests.append(name)
1351a380bf10Simarom            elif f == 0:
1352a380bf10Simarom                passed.append( (name, t) )
1353a380bf10Simarom            else:
1354a380bf10Simarom                failed.append(x)
1355a380bf10Simarom        if verbose:
1356a380bf10Simarom            if notests:
1357a380bf10Simarom                print(len(notests), "items had no tests:")
1358a380bf10Simarom                notests.sort()
1359a380bf10Simarom                for thing in notests:
1360a380bf10Simarom                    print("   ", thing)
1361a380bf10Simarom            if passed:
1362a380bf10Simarom                print(len(passed), "items passed all tests:")
1363a380bf10Simarom                passed.sort()
1364a380bf10Simarom                for thing, count in passed:
1365a380bf10Simarom                    print(" %3d tests in %s" % (count, thing))
1366a380bf10Simarom        if failed:
1367a380bf10Simarom            print(self.DIVIDER)
1368a380bf10Simarom            print(len(failed), "items had failures:")
1369a380bf10Simarom            failed.sort()
1370a380bf10Simarom            for thing, (f, t) in failed:
1371a380bf10Simarom                print(" %3d of %3d in %s" % (f, t, thing))
1372a380bf10Simarom        if verbose:
1373a380bf10Simarom            print(totalt, "tests in", len(self._name2ft), "items.")
1374a380bf10Simarom            print(totalt - totalf, "passed and", totalf, "failed.")
1375a380bf10Simarom        if totalf:
1376a380bf10Simarom            print("***Test Failed***", totalf, "failures.")
1377a380bf10Simarom        elif verbose:
1378a380bf10Simarom            print("Test passed.")
1379a380bf10Simarom        return totalf, totalt
1380a380bf10Simarom
1381a380bf10Simarom    #/////////////////////////////////////////////////////////////////
1382a380bf10Simarom    # Backward compatibility cruft to maintain doctest.master.
1383a380bf10Simarom    #/////////////////////////////////////////////////////////////////
1384a380bf10Simarom    def merge(self, other):
1385a380bf10Simarom        d = self._name2ft
1386a380bf10Simarom        for name, (f, t) in list(other._name2ft.items()):
1387a380bf10Simarom            if name in d:
1388a380bf10Simarom                print("*** DocTestRunner.merge: '" + name + "' in both" \
1389a380bf10Simarom                    " testers; summing outcomes.")
1390a380bf10Simarom                f2, t2 = d[name]
1391a380bf10Simarom                f = f + f2
1392a380bf10Simarom                t = t + t2
1393a380bf10Simarom            d[name] = f, t
1394a380bf10Simarom
1395a380bf10Simaromclass OutputChecker:
1396a380bf10Simarom    """
1397a380bf10Simarom    A class used to check the whether the actual output from a doctest
1398a380bf10Simarom    example matches the expected output.  `OutputChecker` defines two
1399a380bf10Simarom    methods: `check_output`, which compares a given pair of outputs,
1400a380bf10Simarom    and returns true if they match; and `output_difference`, which
1401a380bf10Simarom    returns a string describing the differences between two outputs.
1402a380bf10Simarom    """
1403a380bf10Simarom    def check_output(self, want, got, optionflags):
1404a380bf10Simarom        """
1405a380bf10Simarom        Return True iff the actual output from an example (`got`)
1406a380bf10Simarom        matches the expected output (`want`).  These strings are
1407a380bf10Simarom        always considered to match if they are identical; but
1408a380bf10Simarom        depending on what option flags the test runner is using,
1409a380bf10Simarom        several non-exact match types are also possible.  See the
1410a380bf10Simarom        documentation for `TestRunner` for more information about
1411a380bf10Simarom        option flags.
1412a380bf10Simarom        """
1413a380bf10Simarom        # Handle the common case first, for efficiency:
1414a380bf10Simarom        # if they're string-identical, always return true.
1415a380bf10Simarom        if got == want:
1416a380bf10Simarom            return True
1417a380bf10Simarom
1418a380bf10Simarom        # The values True and False replaced 1 and 0 as the return
1419a380bf10Simarom        # value for boolean comparisons in Python 2.3.
1420a380bf10Simarom        if not (optionflags & DONT_ACCEPT_TRUE_FOR_1):
1421a380bf10Simarom            if (got,want) == ("True\n", "1\n"):
1422a380bf10Simarom                return True
1423a380bf10Simarom            if (got,want) == ("False\n", "0\n"):
1424a380bf10Simarom                return True
1425a380bf10Simarom
1426a380bf10Simarom        # <BLANKLINE> can be used as a special sequence to signify a
1427a380bf10Simarom        # blank line, unless the DONT_ACCEPT_BLANKLINE flag is used.
1428a380bf10Simarom        if not (optionflags & DONT_ACCEPT_BLANKLINE):
1429a380bf10Simarom            # Replace <BLANKLINE> in want with a blank line.
1430a380bf10Simarom            want = re.sub('(?m)^%s\s*?$' % re.escape(BLANKLINE_MARKER),
1431a380bf10Simarom                          '', want)
1432a380bf10Simarom            # If a line in got contains only spaces, then remove the
1433a380bf10Simarom            # spaces.
1434a380bf10Simarom            got = re.sub('(?m)^\s*?$', '', got)
1435a380bf10Simarom            if got == want:
1436a380bf10Simarom                return True
1437a380bf10Simarom
1438a380bf10Simarom        # This flag causes doctest to ignore any differences in the
1439a380bf10Simarom        # contents of whitespace strings.  Note that this can be used
1440a380bf10Simarom        # in conjunction with the ELLIPSIS flag.
1441a380bf10Simarom        if optionflags & NORMALIZE_WHITESPACE:
1442a380bf10Simarom            got = ' '.join(got.split())
1443a380bf10Simarom            want = ' '.join(want.split())
1444a380bf10Simarom            if got == want:
1445a380bf10Simarom                return True
1446a380bf10Simarom
1447a380bf10Simarom        # The ELLIPSIS flag says to let the sequence "..." in `want`
1448a380bf10Simarom        # match any substring in `got`.
1449a380bf10Simarom        if optionflags & ELLIPSIS:
1450a380bf10Simarom            if _ellipsis_match(want, got):
1451a380bf10Simarom                return True
1452a380bf10Simarom
1453a380bf10Simarom        # We didn't find any match; return false.
1454a380bf10Simarom        return False
1455a380bf10Simarom
1456a380bf10Simarom    # Should we do a fancy diff?
1457a380bf10Simarom    def _do_a_fancy_diff(self, want, got, optionflags):
1458a380bf10Simarom        # Not unless they asked for a fancy diff.
1459a380bf10Simarom        if not optionflags & (REPORT_UDIFF |
1460a380bf10Simarom                              REPORT_CDIFF |
1461a380bf10Simarom                              REPORT_NDIFF):
1462a380bf10Simarom            return False
1463a380bf10Simarom
1464a380bf10Simarom        # If expected output uses ellipsis, a meaningful fancy diff is
1465a380bf10Simarom        # too hard ... or maybe not.  In two real-life failures Tim saw,
1466a380bf10Simarom        # a diff was a major help anyway, so this is commented out.
1467a380bf10Simarom        # [todo] _ellipsis_match() knows which pieces do and don't match,
1468a380bf10Simarom        # and could be the basis for a kick-ass diff in this case.
1469a380bf10Simarom        ##if optionflags & ELLIPSIS and ELLIPSIS_MARKER in want:
1470a380bf10Simarom        ##    return False
1471a380bf10Simarom
1472a380bf10Simarom        # ndiff does intraline difference marking, so can be useful even
1473a380bf10Simarom        # for 1-line differences.
1474a380bf10Simarom        if optionflags & REPORT_NDIFF:
1475a380bf10Simarom            return True
1476a380bf10Simarom
1477a380bf10Simarom        # The other diff types need at least a few lines to be helpful.
1478a380bf10Simarom        return want.count('\n') > 2 and got.count('\n') > 2
1479a380bf10Simarom
1480a380bf10Simarom    def output_difference(self, example, got, optionflags):
1481a380bf10Simarom        """
1482a380bf10Simarom        Return a string describing the differences between the
1483a380bf10Simarom        expected output for a given example (`example`) and the actual
1484a380bf10Simarom        output (`got`).  `optionflags` is the set of option flags used
1485a380bf10Simarom        to compare `want` and `got`.
1486a380bf10Simarom        """
1487a380bf10Simarom        want = example.want
1488a380bf10Simarom        # If <BLANKLINE>s are being used, then replace blank lines
1489a380bf10Simarom        # with <BLANKLINE> in the actual output string.
1490a380bf10Simarom        if not (optionflags & DONT_ACCEPT_BLANKLINE):
1491a380bf10Simarom            got = re.sub('(?m)^[ ]*(?=\n)', BLANKLINE_MARKER, got)
1492a380bf10Simarom
1493a380bf10Simarom        # Check if we should use diff.
1494a380bf10Simarom        if self._do_a_fancy_diff(want, got, optionflags):
1495a380bf10Simarom            # Split want & got into lines.
1496a380bf10Simarom            want_lines = want.splitlines(True)  # True == keep line ends
1497a380bf10Simarom            got_lines = got.splitlines(True)
1498a380bf10Simarom            # Use difflib to find their differences.
1499a380bf10Simarom