2637 lines · 96.0 KB · Python
RawDownload
# Module doctest.# Released to the public domain 16-Jan-2001, by Tim Peters (tim@python.org).# Major enhancements and refactoring by:#     Jim Fulton#     Edward Loper # Provided as-is; use at your own risk; no warranty; no promises; enjoy! r"""Module doctest -- a framework for running examples in docstrings. In simplest use, end each module M to be tested with: def _test():    import doctest    doctest.testmod() if __name__ == "__main__":    _test() Then running the module as a script will cause the examples in thedocstrings to get executed and verified: python M.py This won't display anything unless an example fails, in which case thefailing example(s) and the cause(s) of the failure(s) are printed to stdout(why not stderr? because stderr is a lame hack <0.2 wink>), and the finalline of output is "Test failed.". Run it with the -v switch instead: python M.py -v and a detailed report of all examples tried is printed to stdout, alongwith assorted summaries at the end. You can force verbose mode by passing "verbose=True" to testmod, or prohibitit by passing "verbose=False".  In either of those cases, sys.argv is notexamined by testmod. There are a variety of other ways to run doctests, including integrationwith the unittest framework, and support for running non-Python textfiles containing doctests.  There are also many ways to override partsof doctest's default behaviors.  See the Library Reference Manual fordetails.""" __docformat__ = 'reStructuredText en' __all__ = [    # 0, Option Flags    'register_optionflag',    'DONT_ACCEPT_TRUE_FOR_1',    'DONT_ACCEPT_BLANKLINE',    'NORMALIZE_WHITESPACE',    'ELLIPSIS',    'SKIP',    'IGNORE_EXCEPTION_DETAIL',    'COMPARISON_FLAGS',    'REPORT_UDIFF',    'REPORT_CDIFF',    'REPORT_NDIFF',    'REPORT_ONLY_FIRST_FAILURE',    'REPORTING_FLAGS',    # 1. Utility Functions    # 2. Example & DocTest    'Example',    'DocTest',    # 3. Doctest Parser    'DocTestParser',    # 4. Doctest Finder    'DocTestFinder',    # 5. Doctest Runner    'DocTestRunner',    'OutputChecker',    'DocTestFailure',    'UnexpectedException',    'DebugRunner',    # 6. Test Functions    'testmod',    'testfile',    'run_docstring_examples',    # 7. Tester    'Tester',    # 8. Unittest Support    'DocTestSuite',    'DocFileSuite',    'set_unittest_reportflags',    # 9. Debugging Support    'script_from_examples',    'testsource',    'debug_src',    'debug',] import __future__ import sys, traceback, inspect, linecache, os, reimport unittest, difflib, pdb, tempfileimport warningsfrom StringIO import StringIO # There are 4 basic classes:#  - Example: a <source, want> pair, plus an intra-docstring line number.#  - DocTest: a collection of examples, parsed from a docstring, plus#    info about where the docstring came from (name, filename, lineno).#  - DocTestFinder: extracts DocTests from a given object's docstring and#    its contained objects' docstrings.#  - DocTestRunner: runs DocTest cases, and accumulates statistics.## So the basic picture is:##                             list of:# +------+                   +---------+                   +-------+# |object| --DocTestFinder-> | DocTest | --DocTestRunner-> |results|# +------+                   +---------+                   +-------+#                            | Example |#                            |   ...   |#                            | Example |#                            +---------+ # Option constants. OPTIONFLAGS_BY_NAME = {}def register_optionflag(name):    # Create a new flag unless `name` is already known.    return OPTIONFLAGS_BY_NAME.setdefault(name, 1 << len(OPTIONFLAGS_BY_NAME)) DONT_ACCEPT_TRUE_FOR_1 = register_optionflag('DONT_ACCEPT_TRUE_FOR_1')DONT_ACCEPT_BLANKLINE = register_optionflag('DONT_ACCEPT_BLANKLINE')NORMALIZE_WHITESPACE = register_optionflag('NORMALIZE_WHITESPACE')ELLIPSIS = register_optionflag('ELLIPSIS')SKIP = register_optionflag('SKIP')IGNORE_EXCEPTION_DETAIL = register_optionflag('IGNORE_EXCEPTION_DETAIL') COMPARISON_FLAGS = (DONT_ACCEPT_TRUE_FOR_1 |                    DONT_ACCEPT_BLANKLINE |                    NORMALIZE_WHITESPACE |                    ELLIPSIS |                    SKIP |                    IGNORE_EXCEPTION_DETAIL) REPORT_UDIFF = register_optionflag('REPORT_UDIFF')REPORT_CDIFF = register_optionflag('REPORT_CDIFF')REPORT_NDIFF = register_optionflag('REPORT_NDIFF')REPORT_ONLY_FIRST_FAILURE = register_optionflag('REPORT_ONLY_FIRST_FAILURE') REPORTING_FLAGS = (REPORT_UDIFF |                   REPORT_CDIFF |                   REPORT_NDIFF |                   REPORT_ONLY_FIRST_FAILURE) # Special string markers for use in `want` strings:BLANKLINE_MARKER = '<BLANKLINE>'ELLIPSIS_MARKER = '...' ######################################################################## Table of Contents#######################################################################  1. Utility Functions#  2. Example & DocTest -- store test cases#  3. DocTest Parser -- extracts examples from strings#  4. DocTest Finder -- extracts test cases from objects#  5. DocTest Runner -- runs test cases#  6. Test Functions -- convenient wrappers for testing#  7. Tester Class -- for backwards compatibility#  8. Unittest Support#  9. Debugging Support# 10. Example Usage ######################################################################## 1. Utility Functions###################################################################### def _extract_future_flags(globs):    """    Return the compiler-flags associated with the future features that    have been imported into the given namespace (globs).    """    flags = 0    for fname in __future__.all_feature_names:        feature = globs.get(fname, None)        if feature is getattr(__future__, fname):            flags |= feature.compiler_flag    return flags def _normalize_module(module, depth=2):    """    Return the module specified by `module`.  In particular:      - If `module` is a module, then return module.      - If `module` is a string, then import and return the        module with that name.      - If `module` is None, then return the calling module.        The calling module is assumed to be the module of        the stack frame at the given depth in the call stack.    """    if inspect.ismodule(module):        return module    elif isinstance(module, (str, unicode)):        return __import__(module, globals(), locals(), ["*"])    elif module is None:        return sys.modules[sys._getframe(depth).f_globals['__name__']]    else:        raise TypeError("Expected a module, string, or None") def _load_testfile(filename, package, module_relative):    if module_relative:        package = _normalize_module(package, 3)        filename = _module_relative_path(package, filename)        if hasattr(package, '__loader__'):            if hasattr(package.__loader__, 'get_data'):                return package.__loader__.get_data(filename), filename    return open(filename).read(), filename def _indent(s, indent=4):    """    Add the given number of space characters to the beginning every    non-blank line in `s`, and return the result.    """    # This regexp matches the start of non-blank lines:    return re.sub('(?m)^(?!$)', indent*' ', s) 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.class _SpoofOut(StringIO):    def getvalue(self):        result = StringIO.getvalue(self)        # If anything at all was written, make sure there's a trailing        # newline.  There's no way for the expected output to indicate        # that a trailing newline is missing.        if result and not result.endswith("\n"):            result += "\n"        # Prevent softspace from screwing up the next test case, in        # case they used print with a trailing comma in an example.        if hasattr(self, "softspace"):            del self.softspace        return result     def truncate(self,   size=None):        StringIO.truncate(self, size)        if hasattr(self, "softspace"):            del self.softspace # Worst-case linear-time ellipsis matching.def _ellipsis_match(want, got):    """    Essentially the only subtle case:    >>> _ellipsis_match('aa...aa', 'aaa')    False    """    if ELLIPSIS_MARKER not in want:        return want == got     # Find "the real" strings.    ws = want.split(ELLIPSIS_MARKER)    assert len(ws) >= 2     # Deal with exact matches possibly needed at one or both ends.    startpos, endpos = 0, len(got)    w = ws[0]    if w:   # starts with exact match        if got.startswith(w):            startpos = len(w)            del ws[0]        else:            return False    w = ws[-1]    if w:   # ends with exact match        if got.endswith(w):            endpos -= len(w)            del ws[-1]        else:            return False     if startpos > endpos:        # Exact end matches required more characters than we have, as in        # _ellipsis_match('aa...aa', 'aaa')        return False     # For the rest, we only need to find the leftmost non-overlapping    # match for each piece.  If there's no overall match that way alone,    # there's no overall match period.    for w in ws:        # w may be '' at times, if there are consecutive ellipses, or        # due to an ellipsis at the start or end of `want`.  That's OK.        # Search for an empty string succeeds, and doesn't change startpos.        startpos = got.find(w, startpos, endpos)        if startpos < 0:            return False        startpos += len(w)     return True def _comment_line(line):    "Return a commented form of the given line"    line = line.rstrip()    if line:        return '# '+line    else:        return '#' class _OutputRedirectingPdb(pdb.Pdb):    """    A specialized version of the python debugger that redirects stdout    to a given stream when interacting with the user.  Stdout is *not*    redirected when traced code is executed.    """    def __init__(self, out):        self.__out = out        pdb.Pdb.__init__(self, stdout=out)     def trace_dispatch(self, *args):        # Redirect stdout to the given stream.        save_stdout = sys.stdout        sys.stdout = self.__out        # Call Pdb's trace dispatch method.        try:            return pdb.Pdb.trace_dispatch(self, *args)        finally:            sys.stdout = save_stdout # [XX] Normalize with respect to os.path.pardir?def _module_relative_path(module, path):    if not inspect.ismodule(module):        raise TypeError, 'Expected a module: %r' % module    if path.startswith('/'):        raise ValueError, 'Module-relative files may not have absolute paths'     # Find the base directory for the path.    if hasattr(module, '__file__'):        # A normal module/package        basedir = os.path.split(module.__file__)[0]    elif module.__name__ == '__main__':        # An interactive session.        if len(sys.argv)>0 and sys.argv[0] != '':            basedir = os.path.split(sys.argv[0])[0]        else:            basedir = os.curdir    else:        # A module w/o __file__ (this includes builtins)        raise ValueError("Can't resolve paths relative to the module " +                         module + " (it has no __file__)")     # Combine the base directory and the path.    return os.path.join(basedir, *(path.split('/'))) ######################################################################## 2. Example & DocTest######################################################################## - An "example" is a <source, want> pair, where "source" is a##   fragment of source code, and "want" is the expected output for##   "source."  The Example class also includes information about##   where the example was extracted from.#### - A "doctest" is a collection of examples, typically extracted from##   a string (such as an object's docstring).  The DocTest class also##   includes information about where the string was extracted from. class Example:    """    A single doctest example, consisting of source code and expected    output.  `Example` defines the following attributes:       - source: A single Python statement, always ending with a newline.        The constructor adds a newline if needed.       - want: The expected output from running the source code (either        from stdout, or a traceback in case of exception).  `want` ends        with a newline unless it's empty, in which case it's an empty        string.  The constructor adds a newline if needed.       - exc_msg: The exception message generated by the example, if        the example is expected to generate an exception; or `None` if        it is not expected to generate an exception.  This exception        message is compared against the return value of        `traceback.format_exception_only()`.  `exc_msg` ends with a        newline unless it's `None`.  The constructor adds a newline        if needed.       - lineno: The line number within the DocTest string containing        this Example where the Example begins.  This line number is        zero-based, with respect to the beginning of the DocTest.       - indent: The example's indentation in the DocTest string.        I.e., the number of space characters that preceed the        example's first prompt.       - options: A dictionary mapping from option flags to True or        False, which is used to override default options for this        example.  Any option flags not contained in this dictionary        are left at their default value (as specified by the        DocTestRunner's optionflags).  By default, no options are set.    """    def __init__(self, source, want, exc_msg=None, lineno=0, indent=0,                 options=None):        # Normalize inputs.        if not source.endswith('\n'):            source += '\n'        if want and not want.endswith('\n'):            want += '\n'        if exc_msg is not None and not exc_msg.endswith('\n'):            exc_msg += '\n'        # Store properties.        self.source = source        self.want = want        self.lineno = lineno        self.indent = indent        if options is None: options = {}        self.options = options        self.exc_msg = exc_msg class DocTest:    """    A collection of doctest examples that should be run in a single    namespace.  Each `DocTest` defines the following attributes:       - examples: the list of examples.       - globs: The namespace (aka globals) that the examples should        be run in.       - name: A name identifying the DocTest (typically, the name of        the object whose docstring this DocTest was extracted from).       - filename: The name of the file that this DocTest was extracted        from, or `None` if the filename is unknown.       - lineno: The line number within filename where this DocTest        begins, or `None` if the line number is unavailable.  This        line number is zero-based, with respect to the beginning of        the file.       - docstring: The string that the examples were extracted from,        or `None` if the string is unavailable.    """    def __init__(self, examples, globs, name, filename, lineno, docstring):        """        Create a new DocTest containing the given examples.  The        DocTest's globals are initialized with a copy of `globs`.        """        assert not isinstance(examples, basestring), \               "DocTest no longer accepts str; use DocTestParser instead"        self.examples = examples        self.docstring = docstring        self.globs = globs.copy()        self.name = name        self.filename = filename        self.lineno = lineno     def __repr__(self):        if len(self.examples) == 0:            examples = 'no examples'        elif len(self.examples) == 1:            examples = '1 example'        else:            examples = '%d examples' % len(self.examples)        return ('<DocTest %s from %s:%s (%s)>' %                (self.name, self.filename, self.lineno, examples))      # This lets us sort tests by name:    def __cmp__(self, other):        if not isinstance(other, DocTest):            return -1        return cmp((self.name, self.filename, self.lineno, id(self)),                   (other.name, other.filename, other.lineno, id(other))) ######################################################################## 3. DocTestParser###################################################################### class DocTestParser:    """    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'''        # Source consists of a PS1 line followed by zero or more PS2 lines.        (?P<source>            (?:^(?P<indent> [ ]*) >>>    .*)    # PS1 line            (?:\n           [ ]*  \.\.\. .*)*)  # PS2 lines        \n?        # Want consists of any non-blank lines that do not start with PS1.        (?P<want> (?:(?![ ]*$)    # Not a blank line                     (?![ ]*>>>)  # Not a line starting with PS1                     .*$\n?       # But any other line

Lines 1–500 of 2637.