NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

doctest.py (45198B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\stdlib\doctest.py
      2 __docformat__ = 'reStructuredText en'
      3 __all__ = ['register_optionflag',
      4  'DONT_ACCEPT_TRUE_FOR_1',
      5  'DONT_ACCEPT_BLANKLINE',
      6  'NORMALIZE_WHITESPACE',
      7  'ELLIPSIS',
      8  'SKIP',
      9  'IGNORE_EXCEPTION_DETAIL',
     10  'COMPARISON_FLAGS',
     11  'REPORT_UDIFF',
     12  'REPORT_CDIFF',
     13  'REPORT_NDIFF',
     14  'REPORT_ONLY_FIRST_FAILURE',
     15  'REPORTING_FLAGS',
     16  'Example',
     17  'DocTest',
     18  'DocTestParser',
     19  'DocTestFinder',
     20  'DocTestRunner',
     21  'OutputChecker',
     22  'DocTestFailure',
     23  'UnexpectedException',
     24  'DebugRunner',
     25  'testmod',
     26  'testfile',
     27  'run_docstring_examples',
     28  'Tester',
     29  'DocTestSuite',
     30  'DocFileSuite',
     31  'set_unittest_reportflags',
     32  'script_from_examples',
     33  'testsource',
     34  'debug_src',
     35  'debug']
     36 import __future__
     37 import sys, traceback, inspect, linecache, os, re
     38 import unittest, difflib, pdb, tempfile
     39 import warnings
     40 from StringIO import StringIO
     41 from collections import namedtuple
     42 TestResults = namedtuple('TestResults', 'failed attempted')
     43 OPTIONFLAGS_BY_NAME = {}
     44 
     45 def register_optionflag(name):
     46     return OPTIONFLAGS_BY_NAME.setdefault(name, 1 << len(OPTIONFLAGS_BY_NAME))
     47 
     48 
     49 DONT_ACCEPT_TRUE_FOR_1 = register_optionflag('DONT_ACCEPT_TRUE_FOR_1')
     50 DONT_ACCEPT_BLANKLINE = register_optionflag('DONT_ACCEPT_BLANKLINE')
     51 NORMALIZE_WHITESPACE = register_optionflag('NORMALIZE_WHITESPACE')
     52 ELLIPSIS = register_optionflag('ELLIPSIS')
     53 SKIP = register_optionflag('SKIP')
     54 IGNORE_EXCEPTION_DETAIL = register_optionflag('IGNORE_EXCEPTION_DETAIL')
     55 COMPARISON_FLAGS = DONT_ACCEPT_TRUE_FOR_1 | DONT_ACCEPT_BLANKLINE | NORMALIZE_WHITESPACE | ELLIPSIS | SKIP | IGNORE_EXCEPTION_DETAIL
     56 REPORT_UDIFF = register_optionflag('REPORT_UDIFF')
     57 REPORT_CDIFF = register_optionflag('REPORT_CDIFF')
     58 REPORT_NDIFF = register_optionflag('REPORT_NDIFF')
     59 REPORT_ONLY_FIRST_FAILURE = register_optionflag('REPORT_ONLY_FIRST_FAILURE')
     60 REPORTING_FLAGS = REPORT_UDIFF | REPORT_CDIFF | REPORT_NDIFF | REPORT_ONLY_FIRST_FAILURE
     61 BLANKLINE_MARKER = '<BLANKLINE>'
     62 ELLIPSIS_MARKER = '...'
     63 
     64 def _extract_future_flags(globs):
     65     flags = 0
     66     for fname in __future__.all_feature_names:
     67         feature = globs.get(fname, None)
     68         if feature is getattr(__future__, fname):
     69             flags |= feature.compiler_flag
     70 
     71     return flags
     72 
     73 
     74 def _normalize_module(module, depth = 2):
     75     if inspect.ismodule(module):
     76         return module
     77     if isinstance(module, (str, unicode)):
     78         return __import__(module, globals(), locals(), ['*'])
     79     if module is None:
     80         return sys.modules[sys._getframe(depth).f_globals['__name__']]
     81     raise TypeError('Expected a module, string, or None')
     82 
     83 
     84 def _load_testfile(filename, package, module_relative):
     85     if module_relative:
     86         package = _normalize_module(package, 3)
     87         filename = _module_relative_path(package, filename)
     88         if hasattr(package, '__loader__'):
     89             if hasattr(package.__loader__, 'get_data'):
     90                 file_contents = package.__loader__.get_data(filename)
     91                 return (file_contents.replace(os.linesep, '\n'), filename)
     92     with open(filename) as f:
     93         return (f.read(), filename)
     94 
     95 
     96 _encoding = getattr(sys.__stdout__, 'encoding', None) or 'utf-8'
     97 
     98 def _indent(s, indent = 4):
     99     if isinstance(s, unicode):
    100         s = s.encode(_encoding, 'backslashreplace')
    101     return re.sub('(?m)^(?!$)', indent * ' ', s)
    102 
    103 
    104 def _exception_traceback(exc_info):
    105     excout = StringIO()
    106     exc_type, exc_val, exc_tb = exc_info
    107     traceback.print_exception(exc_type, exc_val, exc_tb, file=excout)
    108     return excout.getvalue()
    109 
    110 
    111 class _SpoofOut(StringIO):
    112 
    113     def getvalue(self):
    114         result = StringIO.getvalue(self)
    115         if result and not result.endswith('\n'):
    116             result += '\n'
    117         if hasattr(self, 'softspace'):
    118             del self.softspace
    119         return result
    120 
    121     def truncate(self, size = None):
    122         StringIO.truncate(self, size)
    123         if hasattr(self, 'softspace'):
    124             del self.softspace
    125         if not self.buf:
    126             self.buf = ''
    127 
    128 
    129 def _ellipsis_match(want, got):
    130     if ELLIPSIS_MARKER not in want:
    131         return want == got
    132     ws = want.split(ELLIPSIS_MARKER)
    133     startpos, endpos = 0, len(got)
    134     w = ws[0]
    135     if w:
    136         if got.startswith(w):
    137             startpos = len(w)
    138             del ws[0]
    139         else:
    140             return False
    141     w = ws[-1]
    142     if w:
    143         if got.endswith(w):
    144             endpos -= len(w)
    145             del ws[-1]
    146         else:
    147             return False
    148     if startpos > endpos:
    149         return False
    150     for w in ws:
    151         startpos = got.find(w, startpos, endpos)
    152         if startpos < 0:
    153             return False
    154         startpos += len(w)
    155 
    156     return True
    157 
    158 
    159 def _comment_line(line):
    160     line = line.rstrip()
    161     if line:
    162         return '# ' + line
    163     else:
    164         return '#'
    165 
    166 
    167 class _OutputRedirectingPdb(pdb.Pdb):
    168 
    169     def __init__(self, out):
    170         self.__out = out
    171         self.__debugger_used = False
    172         pdb.Pdb.__init__(self, stdout=out)
    173         self.use_rawinput = 1
    174 
    175     def set_trace(self, frame = None):
    176         self.__debugger_used = True
    177         if frame is None:
    178             frame = sys._getframe().f_back
    179         pdb.Pdb.set_trace(self, frame)
    180 
    181     def set_continue(self):
    182         if self.__debugger_used:
    183             pdb.Pdb.set_continue(self)
    184 
    185     def trace_dispatch(self, *args):
    186         save_stdout = sys.stdout
    187         sys.stdout = self.__out
    188         try:
    189             return pdb.Pdb.trace_dispatch(self, *args)
    190         finally:
    191             sys.stdout = save_stdout
    192 
    193 
    194 def _module_relative_path(module, path):
    195     if not inspect.ismodule(module):
    196         raise TypeError, 'Expected a module: %r' % module
    197     if path.startswith('/'):
    198         raise ValueError, 'Module-relative files may not have absolute paths'
    199     if hasattr(module, '__file__'):
    200         basedir = os.path.split(module.__file__)[0]
    201     elif module.__name__ == '__main__':
    202         if len(sys.argv) > 0 and sys.argv[0] != '':
    203             basedir = os.path.split(sys.argv[0])[0]
    204         else:
    205             basedir = os.curdir
    206     else:
    207         raise ValueError("Can't resolve paths relative to the module " + module + ' (it has no __file__)')
    208     return os.path.join(basedir, *path.split('/'))
    209 
    210 
    211 class Example():
    212 
    213     def __init__(self, source, want, exc_msg = None, lineno = 0, indent = 0, options = None):
    214         if not source.endswith('\n'):
    215             source += '\n'
    216         if want and not want.endswith('\n'):
    217             want += '\n'
    218         if exc_msg is not None and not exc_msg.endswith('\n'):
    219             exc_msg += '\n'
    220         self.source = source
    221         self.want = want
    222         self.lineno = lineno
    223         self.indent = indent
    224         if options is None:
    225             options = {}
    226         self.options = options
    227         self.exc_msg = exc_msg
    228 
    229 
    230 class DocTest():
    231 
    232     def __init__(self, examples, globs, name, filename, lineno, docstring):
    233         self.examples = examples
    234         self.docstring = docstring
    235         self.globs = globs.copy()
    236         self.name = name
    237         self.filename = filename
    238         self.lineno = lineno
    239 
    240     def __repr__(self):
    241         if len(self.examples) == 0:
    242             examples = 'no examples'
    243         elif len(self.examples) == 1:
    244             examples = '1 example'
    245         else:
    246             examples = '%d examples' % len(self.examples)
    247         return '<DocTest %s from %s:%s (%s)>' % (self.name,
    248          self.filename,
    249          self.lineno,
    250          examples)
    251 
    252     def __cmp__(self, other):
    253         if not isinstance(other, DocTest):
    254             return -1
    255         return cmp((self.name,
    256          self.filename,
    257          self.lineno,
    258          id(self)), (other.name,
    259          other.filename,
    260          other.lineno,
    261          id(other)))
    262 
    263 
    264 class DocTestParser():
    265     _EXAMPLE_RE = re.compile('\n        # Source consists of a PS1 line followed by zero or more PS2 lines.\n        (?P<source>\n            (?:^(?P<indent> [ ]*) >>>    .*)    # PS1 line\n            (?:\\n           [ ]*  \\.\\.\\. .*)*)  # PS2 lines\n        \\n?\n        # Want consists of any non-blank lines that do not start with PS1.\n        (?P<want> (?:(?![ ]*$)    # Not a blank line\n                     (?![ ]*>>>)  # Not a line starting with PS1\n                     .*$\\n?       # But any other line\n                  )*)\n        ', re.MULTILINE | re.VERBOSE)
    266     _EXCEPTION_RE = re.compile("\n        # Grab the traceback header.  Different versions of Python have\n        # said different things on the first traceback line.\n        ^(?P<hdr> Traceback\\ \\(\n            (?: most\\ recent\\ call\\ last\n            |   innermost\\ last\n            ) \\) :\n        )\n        \\s* $                # toss trailing whitespace on the header.\n        (?P<stack> .*?)      # don't blink: absorb stuff until...\n        ^ (?P<msg> \\w+ .*)   #     a line *starts* with alphanum.\n        ", re.VERBOSE | re.MULTILINE | re.DOTALL)
    267     _IS_BLANK_OR_COMMENT = re.compile('^[ ]*(#.*)?$').match
    268 
    269     def parse(self, string, name = '<string>'):
    270         string = string.expandtabs()
    271         min_indent = self._min_indent(string)
    272         if min_indent > 0:
    273             string = '\n'.join([ l[min_indent:] for l in string.split('\n') ])
    274         output = []
    275         charno, lineno = (0, 0)
    276         for m in self._EXAMPLE_RE.finditer(string):
    277             output.append(string[charno:m.start()])
    278             lineno += string.count('\n', charno, m.start())
    279             source, options, want, exc_msg = self._parse_example(m, name, lineno)
    280             if not self._IS_BLANK_OR_COMMENT(source):
    281                 output.append(Example(source, want, exc_msg, lineno=lineno, indent=min_indent + len(m.group('indent')), options=options))
    282             lineno += string.count('\n', m.start(), m.end())
    283             charno = m.end()
    284 
    285         output.append(string[charno:])
    286         return output
    287 
    288     def get_doctest(self, string, globs, name, filename, lineno):
    289         return DocTest(self.get_examples(string, name), globs, name, filename, lineno, string)
    290 
    291     def get_examples(self, string, name = '<string>'):
    292         return [ x for x in self.parse(string, name) if isinstance(x, Example) ]
    293 
    294     def _parse_example(self, m, name, lineno):
    295         indent = len(m.group('indent'))
    296         source_lines = m.group('source').split('\n')
    297         self._check_prompt_blank(source_lines, indent, name, lineno)
    298         self._check_prefix(source_lines[1:], ' ' * indent + '.', name, lineno)
    299         source = '\n'.join([ sl[indent + 4:] for sl in source_lines ])
    300         want = m.group('want')
    301         want_lines = want.split('\n')
    302         if len(want_lines) > 1 and re.match(' *$', want_lines[-1]):
    303             del want_lines[-1]
    304         self._check_prefix(want_lines, ' ' * indent, name, lineno + len(source_lines))
    305         want = '\n'.join([ wl[indent:] for wl in want_lines ])
    306         m = self._EXCEPTION_RE.match(want)
    307         if m:
    308             exc_msg = m.group('msg')
    309         else:
    310             exc_msg = None
    311         options = self._find_options(source, name, lineno)
    312         return (source,
    313          options,
    314          want,
    315          exc_msg)
    316 
    317     _OPTION_DIRECTIVE_RE = re.compile('#\\s*doctest:\\s*([^\\n\\\'"]*)$', re.MULTILINE)
    318 
    319     def _find_options(self, source, name, lineno):
    320         options = {}
    321         for m in self._OPTION_DIRECTIVE_RE.finditer(source):
    322             option_strings = m.group(1).replace(',', ' ').split()
    323             for option in option_strings:
    324                 if option[0] not in '+-' or option[1:] not in OPTIONFLAGS_BY_NAME:
    325                     raise ValueError('line %r of the doctest for %s has an invalid option: %r' % (lineno + 1, name, option))
    326                 flag = OPTIONFLAGS_BY_NAME[option[1:]]
    327                 options[flag] = option[0] == '+'
    328 
    329         if options and self._IS_BLANK_OR_COMMENT(source):
    330             raise ValueError('line %r of the doctest for %s has an option directive on a line with no example: %r' % (lineno, name, source))
    331         return options
    332 
    333     _INDENT_RE = re.compile('^([ ]*)(?=\\S)', re.MULTILINE)
    334 
    335     def _min_indent(self, s):
    336         indents = [ len(indent) for indent in self._INDENT_RE.findall(s) ]
    337         if len(indents) > 0:
    338             return min(indents)
    339         else:
    340             return 0
    341 
    342     def _check_prompt_blank(self, lines, indent, name, lineno):
    343         for i, line in enumerate(lines):
    344             if len(line) >= indent + 4 and line[indent + 3] != ' ':
    345                 raise ValueError('line %r of the docstring for %s lacks blank after %s: %r' % (lineno + i + 1,
    346                  name,
    347                  line[indent:indent + 3],
    348                  line))
    349 
    350     def _check_prefix(self, lines, prefix, name, lineno):
    351         for i, line in enumerate(lines):
    352             if line and not line.startswith(prefix):
    353                 raise ValueError('line %r of the docstring for %s has inconsistent leading whitespace: %r' % (lineno + i + 1, name, line))
    354 
    355 
    356 class DocTestFinder():
    357 
    358     def __init__(self, verbose = False, parser = DocTestParser(), recurse = True, exclude_empty = True):
    359         self._parser = parser
    360         self._verbose = verbose
    361         self._recurse = recurse
    362         self._exclude_empty = exclude_empty
    363 
    364     def find(self, obj, name = None, module = None, globs = None, extraglobs = None):
    365         if name is None:
    366             name = getattr(obj, '__name__', None)
    367             if name is None:
    368                 raise ValueError("DocTestFinder.find: name must be given when obj.__name__ doesn't exist: %r" % (type(obj),))
    369         if module is False:
    370             module = None
    371         elif module is None:
    372             module = inspect.getmodule(obj)
    373         try:
    374             file = inspect.getsourcefile(obj) or inspect.getfile(obj)
    375             if module is not None:
    376                 source_lines = linecache.getlines(file, module.__dict__)
    377             else:
    378                 source_lines = linecache.getlines(file)
    379             if not source_lines:
    380                 source_lines = None
    381         except TypeError:
    382             source_lines = None
    383 
    384         if globs is None:
    385             if module is None:
    386                 globs = {}
    387             else:
    388                 globs = module.__dict__.copy()
    389         else:
    390             globs = globs.copy()
    391         if extraglobs is not None:
    392             globs.update(extraglobs)
    393         if '__name__' not in globs:
    394             globs['__name__'] = '__main__'
    395         tests = []
    396         self._find(tests, obj, name, module, source_lines, globs, {})
    397         tests.sort()
    398         return tests
    399 
    400     def _from_module(self, module, object):
    401         if module is None:
    402             return True
    403         if inspect.getmodule(object) is not None:
    404             return module is inspect.getmodule(object)
    405         if inspect.isfunction(object):
    406             return module.__dict__ is object.func_globals
    407         if inspect.isclass(object):
    408             return module.__name__ == object.__module__
    409         if hasattr(object, '__module__'):
    410             return module.__name__ == object.__module__
    411         if isinstance(object, property):
    412             return True
    413         raise ValueError('object must be a class or function')
    414 
    415     def _find(self, tests, obj, name, module, source_lines, globs, seen):
    416         if self._verbose:
    417             print 'Finding tests in %s' % name
    418         if id(obj) in seen:
    419             return
    420         seen[id(obj)] = 1
    421         test = self._get_test(obj, name, module, globs, source_lines)
    422         if test is not None:
    423             tests.append(test)
    424         if inspect.ismodule(obj) and self._recurse:
    425             for valname, val in obj.__dict__.items():
    426                 valname = '%s.%s' % (name, valname)
    427                 if (inspect.isfunction(val) or inspect.isclass(val)) and self._from_module(module, val):
    428                     self._find(tests, val, valname, module, source_lines, globs, seen)
    429 
    430         if inspect.ismodule(obj) and self._recurse:
    431             for valname, val in getattr(obj, '__test__', {}).items():
    432                 if not isinstance(valname, basestring):
    433                     raise ValueError('DocTestFinder.find: __test__ keys must be strings: %r' % (type(valname),))
    434                 if not (inspect.isfunction(val) or inspect.isclass(val) or inspect.ismethod(val) or inspect.ismodule(val) or isinstance(val, basestring)):
    435                     raise ValueError('DocTestFinder.find: __test__ values must be strings, functions, methods, classes, or modules: %r' % (type(val),))
    436                 valname = '%s.__test__.%s' % (name, valname)
    437                 self._find(tests, val, valname, module, source_lines, globs, seen)
    438 
    439         if inspect.isclass(obj) and self._recurse:
    440             for valname, val in obj.__dict__.items():
    441                 if isinstance(val, staticmethod):
    442                     val = getattr(obj, valname)
    443                 if isinstance(val, classmethod):
    444                     val = getattr(obj, valname).im_func
    445                 if (inspect.isfunction(val) or inspect.isclass(val) or isinstance(val, property)) and self._from_module(module, val):
    446                     valname = '%s.%s' % (name, valname)
    447                     self._find(tests, val, valname, module, source_lines, globs, seen)
    448 
    449     def _get_test(self, obj, name, module, globs, source_lines):
    450         if isinstance(obj, basestring):
    451             docstring = obj
    452         else:
    453             try:
    454                 if obj.__doc__ is None:
    455                     docstring = ''
    456                 else:
    457                     docstring = obj.__doc__
    458                     if not isinstance(docstring, basestring):
    459                         docstring = str(docstring)
    460             except (TypeError, AttributeError):
    461                 docstring = ''
    462 
    463         lineno = self._find_lineno(obj, source_lines)
    464         if self._exclude_empty and not docstring:
    465             return
    466         if module is None:
    467             filename = None
    468         else:
    469             filename = getattr(module, '__file__', module.__name__)
    470             if filename[-4:] in ('.pyc', '.pyo'):
    471                 filename = filename[:-1]
    472         return self._parser.get_doctest(docstring, globs, name, filename, lineno)
    473 
    474     def _find_lineno(self, obj, source_lines):
    475         lineno = None
    476         if inspect.ismodule(obj):
    477             lineno = 0
    478         if inspect.isclass(obj):
    479             if source_lines is None:
    480                 return
    481             pat = re.compile('^\\s*class\\s*%s\\b' % getattr(obj, '__name__', '-'))
    482             for i, line in enumerate(source_lines):
    483                 if pat.match(line):
    484                     lineno = i
    485                     break
    486 
    487         if inspect.ismethod(obj):
    488             obj = obj.im_func
    489         if inspect.isfunction(obj):
    490             obj = obj.func_code
    491         if inspect.istraceback(obj):
    492             obj = obj.tb_frame
    493         if inspect.isframe(obj):
    494             obj = obj.f_code
    495         if inspect.iscode(obj):
    496             lineno = getattr(obj, 'co_firstlineno', None) - 1
    497         if lineno is not None:
    498             if source_lines is None:
    499                 return lineno + 1
    500             pat = re.compile('(^|.*:)\\s*\\w*("|\')')
    501             for lineno in range(lineno, len(source_lines)):
    502                 if pat.match(source_lines[lineno]):
    503                     return lineno
    504 
    505 
    506 class DocTestRunner():
    507     DIVIDER = '*' * 70
    508 
    509     def __init__(self, checker = None, verbose = None, optionflags = 0):
    510         self._checker = checker or OutputChecker()
    511         if verbose is None:
    512             verbose = '-v' in sys.argv
    513         self._verbose = verbose
    514         self.optionflags = optionflags
    515         self.original_optionflags = optionflags
    516         self.tries = 0
    517         self.failures = 0
    518         self._name2ft = {}
    519         self._fakeout = _SpoofOut()
    520 
    521     def report_start(self, out, test, example):
    522         if self._verbose:
    523             if example.want:
    524                 out('Trying:\n' + _indent(example.source) + 'Expecting:\n' + _indent(example.want))
    525             else:
    526                 out('Trying:\n' + _indent(example.source) + 'Expecting nothing\n')
    527 
    528     def report_success(self, out, test, example, got):
    529         if self._verbose:
    530             out('ok\n')
    531 
    532     def report_failure(self, out, test, example, got):
    533         out(self._failure_header(test, example) + self._checker.output_difference(example, got, self.optionflags))
    534 
    535     def report_unexpected_exception(self, out, test, example, exc_info):
    536         out(self._failure_header(test, example) + 'Exception raised:\n' + _indent(_exception_traceback(exc_info)))
    537 
    538     def _failure_header(self, test, example):
    539         out = [self.DIVIDER]
    540         if test.filename:
    541             if test.lineno is not None and example.lineno is not None:
    542                 lineno = test.lineno + example.lineno + 1
    543             else:
    544                 lineno = '?'
    545             out.append('File "%s", line %s, in %s' % (test.filename, lineno, test.name))
    546         else:
    547             out.append('Line %s, in %s' % (example.lineno + 1, test.name))
    548         out.append('Failed example:')
    549         source = example.source
    550         out.append(_indent(source))
    551         return '\n'.join(out)
    552 
    553     def __run(self, test, compileflags, out):
    554         failures = tries = 0
    555         original_optionflags = self.optionflags
    556         SUCCESS, FAILURE, BOOM = range(3)
    557         check = self._checker.check_output
    558         for examplenum, example in enumerate(test.examples):
    559             quiet = self.optionflags & REPORT_ONLY_FIRST_FAILURE and failures > 0
    560             self.optionflags = original_optionflags
    561             if example.options:
    562                 for optionflag, val in example.options.items():
    563                     if val:
    564                         self.optionflags |= optionflag
    565                     else:
    566                         self.optionflags &= ~optionflag
    567 
    568             if self.optionflags & SKIP:
    569                 continue
    570             tries += 1
    571             if not quiet:
    572                 self.report_start(out, test, example)
    573             filename = '<doctest %s[%d]>' % (test.name, examplenum)
    574             try:
    575                 exec compile(example.source, filename, 'single', compileflags, 1) in test.globs
    576                 self.debugger.set_continue()
    577                 exception = None
    578             except KeyboardInterrupt:
    579                 raise
    580             except:
    581                 exception = sys.exc_info()
    582                 self.debugger.set_continue()
    583 
    584             got = self._fakeout.getvalue()
    585             self._fakeout.truncate(0)
    586             outcome = FAILURE
    587             if exception is None:
    588                 if check(example.want, got, self.optionflags):
    589                     outcome = SUCCESS
    590             else:
    591                 exc_info = sys.exc_info()
    592                 exc_msg = traceback.format_exception_only(*exc_info[:2])[-1]
    593                 if not quiet:
    594                     got += _exception_traceback(exc_info)
    595                 if example.exc_msg is None:
    596                     outcome = BOOM
    597                 elif check(example.exc_msg, exc_msg, self.optionflags):
    598                     outcome = SUCCESS
    599                 elif self.optionflags & IGNORE_EXCEPTION_DETAIL:
    600                     m1 = re.match('(?:[^:]*\\.)?([^:]*:)', example.exc_msg)
    601                     m2 = re.match('(?:[^:]*\\.)?([^:]*:)', exc_msg)
    602                     if m1 and m2 and check(m1.group(1), m2.group(1), self.optionflags):
    603                         outcome = SUCCESS
    604             if outcome is SUCCESS:
    605                 if not quiet:
    606                     self.report_success(out, test, example, got)
    607             elif outcome is FAILURE:
    608                 if not quiet:
    609                     self.report_failure(out, test, example, got)
    610                 failures += 1
    611             elif outcome is BOOM:
    612                 if not quiet:
    613                     self.report_unexpected_exception(out, test, example, exc_info)
    614                 failures += 1
    615 
    616         self.optionflags = original_optionflags
    617         self.__record_outcome(test, failures, tries)
    618         return TestResults(failures, tries)
    619 
    620     def __record_outcome(self, test, f, t):
    621         f2, t2 = self._name2ft.get(test.name, (0, 0))
    622         self._name2ft[test.name] = (f + f2, t + t2)
    623         self.failures += f
    624         self.tries += t
    625 
    626     __LINECACHE_FILENAME_RE = re.compile('<doctest (?P<name>.+)\\[(?P<examplenum>\\d+)\\]>$')
    627 
    628     def __patched_linecache_getlines(self, filename, module_globals = None):
    629         m = self.__LINECACHE_FILENAME_RE.match(filename)
    630         if m and m.group('name') == self.test.name:
    631             example = self.test.examples[int(m.group('examplenum'))]
    632             source = example.source
    633             if isinstance(source, unicode):
    634                 source = source.encode('ascii', 'backslashreplace')
    635             return source.splitlines(True)
    636         else:
    637             return self.save_linecache_getlines(filename, module_globals)
    638 
    639     def run(self, test, compileflags = None, out = None, clear_globs = True):
    640         self.test = test
    641         if compileflags is None:
    642             compileflags = _extract_future_flags(test.globs)
    643         save_stdout = sys.stdout
    644         if out is None:
    645             out = save_stdout.write
    646         sys.stdout = self._fakeout
    647         save_set_trace = pdb.set_trace
    648         self.debugger = _OutputRedirectingPdb(save_stdout)
    649         self.debugger.reset()
    650         pdb.set_trace = self.debugger.set_trace
    651         self.save_linecache_getlines = linecache.getlines
    652         linecache.getlines = self.__patched_linecache_getlines
    653         save_displayhook = sys.displayhook
    654         sys.displayhook = sys.__displayhook__
    655         try:
    656             return self.__run(test, compileflags, out)
    657         finally:
    658             sys.stdout = save_stdout
    659             pdb.set_trace = save_set_trace
    660             linecache.getlines = self.save_linecache_getlines
    661             sys.displayhook = save_displayhook
    662             if clear_globs:
    663                 test.globs.clear()
    664 
    665     def summarize(self, verbose = None):
    666         if verbose is None:
    667             verbose = self._verbose
    668         notests = []
    669         passed = []
    670         failed = []
    671         totalt = totalf = 0
    672         for x in self._name2ft.items():
    673             name, (f, t) = x
    674             totalt += t
    675             totalf += f
    676             if t == 0:
    677                 notests.append(name)
    678             elif f == 0:
    679                 passed.append((name, t))
    680             else:
    681                 failed.append(x)
    682 
    683         if verbose:
    684             if notests:
    685                 print len(notests), 'items had no tests:'
    686                 notests.sort()
    687                 for thing in notests:
    688                     print '   ', thing
    689 
    690             if passed:
    691                 print len(passed), 'items passed all tests:'
    692                 passed.sort()
    693                 for thing, count in passed:
    694                     print ' %3d tests in %s' % (count, thing)
    695 
    696         if failed:
    697             print self.DIVIDER
    698             print len(failed), 'items had failures:'
    699             failed.sort()
    700             for thing, (f, t) in failed:
    701                 print ' %3d of %3d in %s' % (f, t, thing)
    702 
    703         if verbose:
    704             print totalt, 'tests in', len(self._name2ft), 'items.'
    705             print totalt - totalf, 'passed and', totalf, 'failed.'
    706         if totalf:
    707             print '***Test Failed***', totalf, 'failures.'
    708         elif verbose:
    709             print 'Test passed.'
    710         return TestResults(totalf, totalt)
    711 
    712     def merge(self, other):
    713         d = self._name2ft
    714         for name, (f, t) in other._name2ft.items():
    715             if name in d:
    716                 f2, t2 = d[name]
    717                 f = f + f2
    718                 t = t + t2
    719             d[name] = (f, t)
    720 
    721 
    722 class OutputChecker():
    723 
    724     def check_output(self, want, got, optionflags):
    725         if got == want:
    726             return True
    727         if not optionflags & DONT_ACCEPT_TRUE_FOR_1:
    728             if (got, want) == ('True\n', '1\n'):
    729                 return True
    730             if (got, want) == ('False\n', '0\n'):
    731                 return True
    732         if not optionflags & DONT_ACCEPT_BLANKLINE:
    733             want = re.sub('(?m)^%s\\s*?$' % re.escape(BLANKLINE_MARKER), '', want)
    734             got = re.sub('(?m)^\\s*?$', '', got)
    735             if got == want:
    736                 return True
    737         if optionflags & NORMALIZE_WHITESPACE:
    738             got = ' '.join(got.split())
    739             want = ' '.join(want.split())
    740             if got == want:
    741                 return True
    742         if optionflags & ELLIPSIS:
    743             if _ellipsis_match(want, got):
    744                 return True
    745         return False
    746 
    747     def _do_a_fancy_diff(self, want, got, optionflags):
    748         if not optionflags & (REPORT_UDIFF | REPORT_CDIFF | REPORT_NDIFF):
    749             return False
    750         if optionflags & REPORT_NDIFF:
    751             return True
    752         return want.count('\n') > 2 and got.count('\n') > 2
    753 
    754     def output_difference(self, example, got, optionflags):
    755         want = example.want
    756         if not optionflags & DONT_ACCEPT_BLANKLINE:
    757             got = re.sub('(?m)^[ ]*(?=\n)', BLANKLINE_MARKER, got)
    758         if self._do_a_fancy_diff(want, got, optionflags):
    759             want_lines = want.splitlines(True)
    760             got_lines = got.splitlines(True)
    761             if optionflags & REPORT_UDIFF:
    762                 diff = difflib.unified_diff(want_lines, got_lines, n=2)
    763                 diff = list(diff)[2:]
    764                 kind = 'unified diff with -expected +actual'
    765             elif optionflags & REPORT_CDIFF:
    766                 diff = difflib.context_diff(want_lines, got_lines, n=2)
    767                 diff = list(diff)[2:]
    768                 kind = 'context diff with expected followed by actual'
    769             elif optionflags & REPORT_NDIFF:
    770                 engine = difflib.Differ(charjunk=difflib.IS_CHARACTER_JUNK)
    771                 diff = list(engine.compare(want_lines, got_lines))
    772                 kind = 'ndiff with -expected +actual'
    773             diff = [ line.rstrip() + '\n' for line in diff ]
    774             return 'Differences (%s):\n' % kind + _indent(''.join(diff))
    775         elif want and got:
    776             return 'Expected:\n%sGot:\n%s' % (_indent(want), _indent(got))
    777         elif want:
    778             return 'Expected:\n%sGot nothing\n' % _indent(want)
    779         elif got:
    780             return 'Expected nothing\nGot:\n%s' % _indent(got)
    781         else:
    782             return 'Expected nothing\nGot nothing\n'
    783 
    784 
    785 class DocTestFailure(Exception):
    786 
    787     def __init__(self, test, example, got):
    788         self.test = test
    789         self.example = example
    790         self.got = got
    791 
    792     def __str__(self):
    793         return str(self.test)
    794 
    795 
    796 class UnexpectedException(Exception):
    797 
    798     def __init__(self, test, example, exc_info):
    799         self.test = test
    800         self.example = example
    801         self.exc_info = exc_info
    802 
    803     def __str__(self):
    804         return str(self.test)
    805 
    806 
    807 class DebugRunner(DocTestRunner):
    808 
    809     def run(self, test, compileflags = None, out = None, clear_globs = True):
    810         r = DocTestRunner.run(self, test, compileflags, out, False)
    811         if clear_globs:
    812             test.globs.clear()
    813         return r
    814 
    815     def report_unexpected_exception(self, out, test, example, exc_info):
    816         raise UnexpectedException(test, example, exc_info)
    817 
    818     def report_failure(self, out, test, example, got):
    819         raise DocTestFailure(test, example, got)
    820 
    821 
    822 master = None
    823 
    824 def testmod(m = None, name = None, globs = None, verbose = None, report = True, optionflags = 0, extraglobs = None, raise_on_error = False, exclude_empty = False):
    825     global master
    826     if m is None:
    827         m = sys.modules.get('__main__')
    828     if not inspect.ismodule(m):
    829         raise TypeError('testmod: module required; %r' % (m,))
    830     if name is None:
    831         name = m.__name__
    832     finder = DocTestFinder(exclude_empty=exclude_empty)
    833     if raise_on_error:
    834         runner = DebugRunner(verbose=verbose, optionflags=optionflags)
    835     else:
    836         runner = DocTestRunner(verbose=verbose, optionflags=optionflags)
    837     for test in finder.find(m, name, globs=globs, extraglobs=extraglobs):
    838         runner.run(test)
    839 
    840     if report:
    841         runner.summarize()
    842     if master is None:
    843         master = runner
    844     else:
    845         master.merge(runner)
    846     return TestResults(runner.failures, runner.tries)
    847 
    848 
    849 def testfile(filename, module_relative = True, name = None, package = None, globs = None, verbose = None, report = True, optionflags = 0, extraglobs = None, raise_on_error = False, parser = DocTestParser(), encoding = None):
    850     global master
    851     if package and not module_relative:
    852         raise ValueError('Package may only be specified for module-relative paths.')
    853     text, filename = _load_testfile(filename, package, module_relative)
    854     if name is None:
    855         name = os.path.basename(filename)
    856     if globs is None:
    857         globs = {}
    858     else:
    859         globs = globs.copy()
    860     if extraglobs is not None:
    861         globs.update(extraglobs)
    862     if '__name__' not in globs:
    863         globs['__name__'] = '__main__'
    864     if raise_on_error:
    865         runner = DebugRunner(verbose=verbose, optionflags=optionflags)
    866     else:
    867         runner = DocTestRunner(verbose=verbose, optionflags=optionflags)
    868     if encoding is not None:
    869         text = text.decode(encoding)
    870     test = parser.get_doctest(text, globs, name, filename, 0)
    871     runner.run(test)
    872     if report:
    873         runner.summarize()
    874     if master is None:
    875         master = runner
    876     else:
    877         master.merge(runner)
    878     return TestResults(runner.failures, runner.tries)
    879 
    880 
    881 def run_docstring_examples(f, globs, verbose = False, name = 'NoName', compileflags = None, optionflags = 0):
    882     finder = DocTestFinder(verbose=verbose, recurse=False)
    883     runner = DocTestRunner(verbose=verbose, optionflags=optionflags)
    884     for test in finder.find(f, name, globs=globs):
    885         runner.run(test, compileflags=compileflags)
    886 
    887 
    888 class Tester():
    889 
    890     def __init__(self, mod = None, globs = None, verbose = None, optionflags = 0):
    891         warnings.warn('class Tester is deprecated; use class doctest.DocTestRunner instead', DeprecationWarning, stacklevel=2)
    892         if mod is None and globs is None:
    893             raise TypeError('Tester.__init__: must specify mod or globs')
    894         if mod is not None and not inspect.ismodule(mod):
    895             raise TypeError('Tester.__init__: mod must be a module; %r' % (mod,))
    896         if globs is None:
    897             globs = mod.__dict__
    898         self.globs = globs
    899         self.verbose = verbose
    900         self.optionflags = optionflags
    901         self.testfinder = DocTestFinder()
    902         self.testrunner = DocTestRunner(verbose=verbose, optionflags=optionflags)
    903 
    904     def runstring(self, s, name):
    905         test = DocTestParser().get_doctest(s, self.globs, name, None, None)
    906         if self.verbose:
    907             print 'Running string', name
    908         f, t = self.testrunner.run(test)
    909         if self.verbose:
    910             print f, 'of', t, 'examples failed in string', name
    911         return TestResults(f, t)
    912 
    913     def rundoc(self, object, name = None, module = None):
    914         f = t = 0
    915         tests = self.testfinder.find(object, name, module=module, globs=self.globs)
    916         for test in tests:
    917             f2, t2 = self.testrunner.run(test)
    918             f, t = f + f2, t + t2
    919 
    920         return TestResults(f, t)
    921 
    922     def rundict(self, d, name, module = None):
    923         import types
    924         m = types.ModuleType(name)
    925         m.__dict__.update(d)
    926         if module is None:
    927             module = False
    928         return self.rundoc(m, name, module)
    929 
    930     def run__test__(self, d, name):
    931         import types
    932         m = types.ModuleType(name)
    933         m.__test__ = d
    934         return self.rundoc(m, name)
    935 
    936     def summarize(self, verbose = None):
    937         return self.testrunner.summarize(verbose)
    938 
    939     def merge(self, other):
    940         self.testrunner.merge(other.testrunner)
    941 
    942 
    943 _unittest_reportflags = 0
    944 
    945 def set_unittest_reportflags(flags):
    946     global _unittest_reportflags
    947     if flags & REPORTING_FLAGS != flags:
    948         raise ValueError('Only reporting flags allowed', flags)
    949     old = _unittest_reportflags
    950     _unittest_reportflags = flags
    951     return old
    952 
    953 
    954 class DocTestCase(unittest.TestCase):
    955 
    956     def __init__(self, test, optionflags = 0, setUp = None, tearDown = None, checker = None):
    957         unittest.TestCase.__init__(self)
    958         self._dt_optionflags = optionflags
    959         self._dt_checker = checker
    960         self._dt_test = test
    961         self._dt_setUp = setUp
    962         self._dt_tearDown = tearDown
    963 
    964     def setUp(self):
    965         test = self._dt_test
    966         if self._dt_setUp is not None:
    967             self._dt_setUp(test)
    968 
    969     def tearDown(self):
    970         test = self._dt_test
    971         if self._dt_tearDown is not None:
    972             self._dt_tearDown(test)
    973         test.globs.clear()
    974 
    975     def runTest(self):
    976         test = self._dt_test
    977         old = sys.stdout
    978         new = StringIO()
    979         optionflags = self._dt_optionflags
    980         if not optionflags & REPORTING_FLAGS:
    981             optionflags |= _unittest_reportflags
    982         runner = DocTestRunner(optionflags=optionflags, checker=self._dt_checker, verbose=False)
    983         try:
    984             runner.DIVIDER = '-' * 70
    985             failures, tries = runner.run(test, out=new.write, clear_globs=False)
    986         finally:
    987             sys.stdout = old
    988 
    989         if failures:
    990             raise self.failureException(self.format_failure(new.getvalue()))
    991 
    992     def format_failure(self, err):
    993         test = self._dt_test
    994         if test.lineno is None:
    995             lineno = 'unknown line number'
    996         else:
    997             lineno = '%s' % test.lineno
    998         lname = '.'.join(test.name.split('.')[-1:])
    999         return 'Failed doctest test for %s\n  File "%s", line %s, in %s\n\n%s' % (test.name,
   1000          test.filename,
   1001          lineno,
   1002          lname,
   1003          err)
   1004 
   1005     def debug(self):
   1006         self.setUp()
   1007         runner = DebugRunner(optionflags=self._dt_optionflags, checker=self._dt_checker, verbose=False)
   1008         runner.run(self._dt_test, clear_globs=False)
   1009         self.tearDown()
   1010 
   1011     def id(self):
   1012         return self._dt_test.name
   1013 
   1014     def __repr__(self):
   1015         name = self._dt_test.name.split('.')
   1016         return '%s (%s)' % (name[-1], '.'.join(name[:-1]))
   1017 
   1018     __str__ = __repr__
   1019 
   1020     def shortDescription(self):
   1021         return 'Doctest: ' + self._dt_test.name
   1022 
   1023 
   1024 class SkipDocTestCase(DocTestCase):
   1025 
   1026     def __init__(self):
   1027         DocTestCase.__init__(self, None)
   1028 
   1029     def setUp(self):
   1030         self.skipTest('DocTestSuite will not work with -O2 and above')
   1031 
   1032     def test_skip(self):
   1033         pass
   1034 
   1035     def shortDescription(self):
   1036         return 'Skipping tests from %s' % module.__name__
   1037 
   1038 
   1039 def DocTestSuite(module = None, globs = None, extraglobs = None, test_finder = None, **options):
   1040     if test_finder is None:
   1041         test_finder = DocTestFinder()
   1042     module = _normalize_module(module)
   1043     tests = test_finder.find(module, globs=globs, extraglobs=extraglobs)
   1044     if not tests and sys.flags.optimize >= 2:
   1045         suite = unittest.TestSuite()
   1046         suite.addTest(SkipDocTestCase())
   1047         return suite
   1048     if not tests:
   1049         raise ValueError(module, 'has no tests')
   1050     tests.sort()
   1051     suite = unittest.TestSuite()
   1052     for test in tests:
   1053         if len(test.examples) == 0:
   1054             continue
   1055         if not test.filename:
   1056             filename = module.__file__
   1057             if filename[-4:] in ('.pyc', '.pyo'):
   1058                 filename = filename[:-1]
   1059             test.filename = filename
   1060         suite.addTest(DocTestCase(test, **options))
   1061 
   1062     return suite
   1063 
   1064 
   1065 class DocFileCase(DocTestCase):
   1066 
   1067     def id(self):
   1068         return '_'.join(self._dt_test.name.split('.'))
   1069 
   1070     def __repr__(self):
   1071         return self._dt_test.filename
   1072 
   1073     __str__ = __repr__
   1074 
   1075     def format_failure(self, err):
   1076         return 'Failed doctest test for %s\n  File "%s", line 0\n\n%s' % (self._dt_test.name, self._dt_test.filename, err)
   1077 
   1078 
   1079 def DocFileTest(path, module_relative = True, package = None, globs = None, parser = DocTestParser(), encoding = None, **options):
   1080     if globs is None:
   1081         globs = {}
   1082     else:
   1083         globs = globs.copy()
   1084     if package and not module_relative:
   1085         raise ValueError('Package may only be specified for module-relative paths.')
   1086     doc, path = _load_testfile(path, package, module_relative)
   1087     if '__file__' not in globs:
   1088         globs['__file__'] = path
   1089     name = os.path.basename(path)
   1090     if encoding is not None:
   1091         doc = doc.decode(encoding)
   1092     test = parser.get_doctest(doc, globs, name, path, 0)
   1093     return DocFileCase(test, **options)
   1094 
   1095 
   1096 def DocFileSuite(*paths, **kw):
   1097     suite = unittest.TestSuite()
   1098     if kw.get('module_relative', True):
   1099         kw['package'] = _normalize_module(kw.get('package'))
   1100     for path in paths:
   1101         suite.addTest(DocFileTest(path, **kw))
   1102 
   1103     return suite
   1104 
   1105 
   1106 def script_from_examples(s):
   1107     output = []
   1108     for piece in DocTestParser().parse(s):
   1109         if isinstance(piece, Example):
   1110             output.append(piece.source[:-1])
   1111             want = piece.want
   1112             if want:
   1113                 output.append('# Expected:')
   1114                 output += [ '## ' + l for l in want.split('\n')[:-1] ]
   1115         else:
   1116             output += [ _comment_line(l) for l in piece.split('\n')[:-1] ]
   1117 
   1118     while output and output[-1] == '#':
   1119         output.pop()
   1120 
   1121     while output and output[0] == '#':
   1122         output.pop(0)
   1123 
   1124     return '\n'.join(output) + '\n'
   1125 
   1126 
   1127 def testsource(module, name):
   1128     module = _normalize_module(module)
   1129     tests = DocTestFinder().find(module)
   1130     test = [ t for t in tests if t.name == name ]
   1131     if not test:
   1132         raise ValueError(name, 'not found in tests')
   1133     test = test[0]
   1134     testsrc = script_from_examples(test.docstring)
   1135     return testsrc
   1136 
   1137 
   1138 def debug_src(src, pm = False, globs = None):
   1139     testsrc = script_from_examples(src)
   1140     debug_script(testsrc, pm, globs)
   1141 
   1142 
   1143 def debug_script(src, pm = False, globs = None):
   1144     import pdb
   1145     srcfilename = tempfile.mktemp('.py', 'doctestdebug')
   1146     f = open(srcfilename, 'w')
   1147     f.write(src)
   1148     f.close()
   1149     try:
   1150         if globs:
   1151             globs = globs.copy()
   1152         else:
   1153             globs = {}
   1154         if pm:
   1155             try:
   1156                 execfile(srcfilename, globs, globs)
   1157             except:
   1158                 print sys.exc_info()[1]
   1159                 pdb.post_mortem(sys.exc_info()[2])
   1160 
   1161         else:
   1162             pdb.run('execfile(%r)' % srcfilename, globs, globs)
   1163     finally:
   1164         os.remove(srcfilename)
   1165 
   1166 
   1167 def debug(module, name, pm = False):
   1168     module = _normalize_module(module)
   1169     testsrc = testsource(module, name)
   1170     debug_script(testsrc, pm, module.__dict__)
   1171 
   1172 
   1173 class _TestClass():
   1174 
   1175     def __init__(self, val):
   1176         self.val = val
   1177 
   1178     def square(self):
   1179         self.val = self.val ** 2
   1180         return self
   1181 
   1182     def get(self):
   1183         return self.val
   1184 
   1185 
   1186 __test__ = {'_TestClass': _TestClass,
   1187  'string': '\n                      Example of a string object, searched as-is.\n                      >>> x = 1; y = 2\n                      >>> x + y, x * y\n                      (3, 2)\n                      ',
   1188  'bool-int equivalence': '\n                                    In 2.2, boolean expressions displayed\n                                    0 or 1.  By default, we still accept\n                                    them.  This can be disabled by passing\n                                    DONT_ACCEPT_TRUE_FOR_1 to the new\n                                    optionflags argument.\n                                    >>> 4 == 4\n                                    1\n                                    >>> 4 == 4\n                                    True\n                                    >>> 4 > 4\n                                    0\n                                    >>> 4 > 4\n                                    False\n                                    ',
   1189  'blank lines': "\n                Blank lines can be marked with <BLANKLINE>:\n                    >>> print 'foo\\n\\nbar\\n'\n                    foo\n                    <BLANKLINE>\n                    bar\n                    <BLANKLINE>\n            ",
   1190  'ellipsis': "\n                If the ellipsis flag is used, then '...' can be used to\n                elide substrings in the desired output:\n                    >>> print range(1000) #doctest: +ELLIPSIS\n                    [0, 1, 2, ..., 999]\n            ",
   1191  'whitespace normalization': '\n                If the whitespace normalization flag is used, then\n                differences in whitespace are ignored.\n                    >>> print range(30) #doctest: +NORMALIZE_WHITESPACE\n                    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,\n                     15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,\n                     27, 28, 29]\n            '}
   1192 
   1193 def _test():
   1194     testfiles = [ arg for arg in sys.argv[1:] if arg and arg[0] != '-' ]
   1195     if not testfiles:
   1196         name = os.path.basename(sys.argv[0])
   1197         if '__loader__' in globals():
   1198             name, _ = os.path.splitext(name)
   1199         print 'usage: {0} [-v] file ...'.format(name)
   1200         return 2
   1201     for filename in testfiles:
   1202         if filename.endswith('.py'):
   1203             dirname, filename = os.path.split(filename)
   1204             sys.path.insert(0, dirname)
   1205             m = __import__(filename[:-3])
   1206             del sys.path[0]
   1207             failures, _ = testmod(m)
   1208         else:
   1209             failures, _ = testfile(filename, module_relative=False)
   1210         if failures:
   1211             return 1
   1212 
   1213     return 0
   1214 
   1215 
   1216 if __name__ == '__main__':
   1217     sys.exit(_test())