diff --git a/Lib/doctest.py b/Lib/doctest.py index ce899d66988c3b..749a187bc3742f 100644 --- a/Lib/doctest.py +++ b/Lib/doctest.py @@ -147,10 +147,13 @@ def __repr__(self): # 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') @@ -194,6 +197,7 @@ def register_optionflag(name): # 8. Debugging Support # 9. Example Usage + ###################################################################### ## 1. Utility Functions ###################################################################### @@ -210,6 +214,7 @@ def _extract_future_flags(globs): flags |= feature.compiler_flag return flags + def _normalize_module(module, depth=2): """ Return the module specified by `module`. In particular: @@ -235,10 +240,12 @@ def _normalize_module(module, depth=2): else: raise TypeError("Expected a module, string, or None") + def _newline_convert(data): # The IO module provides a handy decoder for universal newline conversion return IncrementalNewlineDecoder(None, True).decode(data, True) + def _load_testfile(filename, package, module_relative, encoding): if module_relative: package = _normalize_module(package, 3) @@ -257,6 +264,7 @@ def _load_testfile(filename, package, module_relative, encoding): with open(filename, encoding=encoding) as f: return f.read(), filename + def _indent(s, indent=4): """ Add the given number of space characters to the beginning of @@ -265,6 +273,7 @@ def _indent(s, indent=4): # 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 @@ -276,6 +285,7 @@ def _exception_traceback(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): @@ -291,6 +301,7 @@ def truncate(self, size=None): self.seek(size) StringIO.truncate(self) + # Worst-case linear-time ellipsis matching. def _ellipsis_match(want, got): """ @@ -341,6 +352,7 @@ def _ellipsis_match(want, got): return True + def _comment_line(line): "Return a commented form of the given line" line = line.rstrip() @@ -349,6 +361,7 @@ def _comment_line(line): else: return '#' + def _strip_exception_details(msg): # Support for IGNORE_EXCEPTION_DETAIL. # Get rid of everything except the exception name; in particular, drop @@ -375,6 +388,7 @@ def _strip_exception_details(msg): start = i+1 return msg[start: end] + class _OutputRedirectingPdb(pdb.Pdb): """ A specialized version of the python debugger that redirects stdout @@ -411,6 +425,7 @@ def trace_dispatch(self, *args): finally: sys.stdout = save_stdout + # [XX] Normalize with respect to os.path.pardir? def _module_relative_path(module, test_path): if not inspect.ismodule(module): @@ -446,6 +461,7 @@ def _module_relative_path(module, test_path): # Combine the base directory and the test path. return os.path.join(basedir, test_path) + ###################################################################### ## 2. Example & DocTest ###################################################################### @@ -526,6 +542,7 @@ def __hash__(self): return hash((self.source, self.want, self.lineno, self.indent, self.exc_msg)) + class DocTest: """ A collection of doctest examples that should be run in a single @@ -599,6 +616,7 @@ def __lt__(self, other): < (other.name, other.filename, other_lno, id(other))) + ###################################################################### ## 3. DocTestParser ###################################################################### @@ -1164,6 +1182,7 @@ def _find_lineno(self, obj, source_lines): # We couldn't find the line number. return None + ###################################################################### ## 5. DocTest Runner ###################################################################### @@ -1483,6 +1502,7 @@ def __record_outcome(self, test, failures, tries, skips): __LINECACHE_FILENAME_RE = re.compile(r'<doctest ' r'(?P<name>.+)' r'\[(?P<examplenum>\d+)\]>$') + def __patched_linecache_getlines(self, filename, module_globals=None): m = self.__LINECACHE_FILENAME_RE.match(filename) if m and m.group('name') == self.test.name: @@ -1819,6 +1839,7 @@ def output_difference(self, example, got, optionflags): else: return 'Expected nothing\nGot nothing\n' + class DocTestFailure(Exception): """A DocTest example has failed in debugging mode. @@ -1838,6 +1859,7 @@ def __init__(self, test, example, got): def __str__(self): return str(self.test) + class UnexpectedException(Exception): """A DocTest example has encountered an unexpected exception @@ -1857,6 +1879,7 @@ def __init__(self, test, example, exc_info): def __str__(self): return str(self.test) + class DebugRunner(DocTestRunner): r"""Run doc tests but raise an exception as soon as there is a failure. @@ -1960,6 +1983,7 @@ def report_unexpected_exception(self, out, test, example, exc_info): def report_failure(self, out, test, example, got): raise DocTestFailure(test, example, got) + ###################################################################### ## 6. Test Functions ###################################################################### @@ -1969,6 +1993,7 @@ def report_failure(self, out, test, example, got): # class, updated by testmod. master = None + def testmod(m=None, name=None, globs=None, verbose=None, report=True, optionflags=0, extraglobs=None, raise_on_error=False, exclude_empty=False): @@ -2221,12 +2246,14 @@ def run_docstring_examples(f, globs, verbose=False, name="NoName", for test in finder.find(f, name, globs=globs): runner.run(test, compileflags=compileflags) + ###################################################################### ## 7. Unittest Support ###################################################################### _unittest_reportflags = 0 + def set_unittest_reportflags(flags): """Sets the unittest option flags. @@ -2427,6 +2454,7 @@ def __repr__(self): def shortDescription(self): return "Doctest: " + self._dt_test.name + class SkipDocTestCase(DocTestCase): def __init__(self, module): self.module = module @@ -2514,6 +2542,7 @@ def DocTestSuite(module=None, globs=None, extraglobs=None, test_finder=None, return suite + class DocFileCase(DocTestCase): def id(self): @@ -2527,6 +2556,7 @@ def format_failure(self, err): % (self._dt_test.name, self._dt_test.filename, err) ) + def DocFileTest(path, module_relative=True, package=None, globs=None, parser=DocTestParser(), encoding=None, **options): @@ -2553,6 +2583,7 @@ def DocFileTest(path, module_relative=True, package=None, test = parser.get_doctest(doc, globs, name, path, 0) return DocFileCase(test, **options) + def DocFileSuite(*paths, **kw): """A unittest suite for one or more doctest files. @@ -2622,6 +2653,7 @@ def DocFileSuite(*paths, **kw): return suite + ###################################################################### ## 8. Debugging Support ###################################################################### @@ -2708,6 +2740,7 @@ def script_from_examples(s): # Add a courtesy newline to prevent exec from choking (see bug #1172785) return '\n'.join(output) + '\n' + def testsource(module, name): """Extract the test sources from a doctest docstring as a script. @@ -2724,11 +2757,13 @@ def testsource(module, name): testsrc = script_from_examples(test.docstring) return testsrc + def debug_src(src, pm=False, globs=None): """Debug a single doctest docstring, in argument `src`'""" testsrc = script_from_examples(src) debug_script(testsrc, pm, globs) + def debug_script(src, pm=False, globs=None): "Debug a test script. `src` is the script, as a string." import pdb @@ -2749,6 +2784,7 @@ def debug_script(src, pm=False, globs=None): else: pdb.Pdb(nosigint=True).run("exec(%r)" % src, globs, globs) + def debug(module, name, pm=False): """Debug a single doctest docstring. @@ -2760,6 +2796,7 @@ def debug(module, name, pm=False): testsrc = testsource(module, name) debug_script(testsrc, pm, module.__dict__) + ###################################################################### ## 9. Example Usage ###################################################################### @@ -2807,6 +2844,7 @@ def get(self): return self.val + __test__ = {"_TestClass": _TestClass, "string": r""" Example of a string object, searched as-is. diff --git a/Lib/test/test_doctest/test_doctest.py b/Lib/test/test_doctest/test_doctest.py index 13ab3c9e6ca200..e1727aa9b17b2d 100644 --- a/Lib/test/test_doctest/test_doctest.py +++ b/Lib/test/test_doctest/test_doctest.py @@ -43,6 +43,7 @@ def sample_func(v): """ return v+v + class SampleClass: """ >>> print(1) @@ -135,11 +136,14 @@ def __init__(self, val=0): 0 """ self.val = val + def square(self): return SampleClass.NestedClass(self.val*self.val) + def get(self): return self.val + class SampleNewStyleClass(object): r""" >>> print('1\n2\n3') @@ -168,6 +172,7 @@ def get(self): """ return self.val + ###################################################################### ## Test Cases ###################################################################### @@ -293,6 +298,7 @@ def test_Example(): r""" True """ + def test_DocTest(): r""" Unit tests for the `DocTest` class. @@ -443,6 +449,7 @@ def test_DocTest(): r""" """ + class test_DocTestFinder: def basics(): r""" Unit tests for the `DocTestFinder` class. @@ -828,6 +835,7 @@ def test_empty_namespace_package(self): self.assertEqual(len(include_empty_finder.find(mod)), 1) self.assertEqual(len(exclude_empty_finder.find(mod)), 0) + def test_DocTestParser(): r""" Unit tests for the `DocTestParser` class. @@ -883,6 +891,7 @@ def test_DocTestParser(): r""" ('x+y\n', '5\n', 9) """ + class test_DocTestRunner: def basics(): r""" Unit tests for the `DocTestRunner` class. @@ -1928,6 +1937,7 @@ def option_directives(): r""" ValueError: line 0 of the doctest for s has an option directive on a line with no example: '# doctest: +ELLIPSIS' """ + def test_testsource(): r""" Unit tests for `testsource()`. @@ -1968,6 +1978,7 @@ def test_testsource(): r""" <BLANKLINE> """ + def test_debug(): r""" Create a docstring that we want to debug: @@ -1998,6 +2009,7 @@ def test_debug(): r""" """ + if not hasattr(sys, 'gettrace') or not sys.gettrace(): def test_pdb_set_trace(): """Using pdb.set_trace from a doctest. @@ -2219,6 +2231,7 @@ def test_pdb_set_trace_nested(): TestResults(failed=0, attempted=2) """ + def test_DocTestSuite(): """DocTestSuite creates a unittest test suite from a doctest. @@ -2346,6 +2359,7 @@ def test_DocTestSuite(): automatically cleared for us after a test. """ + def test_DocFileSuite(): """We can test tests found in text files using a DocFileSuite. @@ -2525,6 +2539,7 @@ def test_DocFileSuite(): """ + def test_trailing_space_in_test(): """ Trailing spaces in expected output are significant: @@ -2534,6 +2549,7 @@ def test_trailing_space_in_test(): foo \n """ + class Wrapper: def __init__(self, func): self.func = func @@ -2542,6 +2558,7 @@ def __init__(self, func): def __call__(self, *args, **kwargs): self.func(*args, **kwargs) + @Wrapper def test_look_in_unwrapped(): """ @@ -2551,6 +2568,7 @@ def test_look_in_unwrapped(): 'one other test' """ + def test_unittest_reportflags(): """Default unittest reporting flags can be set to control reporting @@ -2630,6 +2648,7 @@ def test_unittest_reportflags(): """ + def test_testfile(): r""" Tests for the `testfile()` function. This function runs all the doctest examples in a given file. In its simple invocation, it is @@ -2809,6 +2828,7 @@ def test_testfile(): r""" >>> _colorize._COLORIZE = save_colorize """ + class TestImporter(importlib.abc.MetaPathFinder, importlib.abc.ResourceLoader): def find_spec(self, fullname, path, target=None): @@ -2818,6 +2838,7 @@ def get_data(self, path): with open(path, mode='rb') as f: return f.read() + class TestHook: def __init__(self, pathdir): @@ -2922,6 +2943,7 @@ def test_lineendings(): r""" """ + def test_testmod(): r""" Tests for the testmod function. More might be useful, but for now we're just testing the case raised by Issue 6195, where trying to doctest a C module would @@ -2933,6 +2955,7 @@ def test_testmod(): r""" TestResults(failed=0, attempted=0) """ + try: os.fsencode("foo-bär@baz.py") supports_unicode = True @@ -2971,6 +2994,7 @@ def test_unicode(): """ TestResults(failed=1, attempted=1) """ + def test_CLI(): r""" The doctest module can be used to run doctests against an arbitrary file. These tests test this CLI functionality. @@ -3201,6 +3225,7 @@ def test_CLI(): r""" """ + def test_no_trailing_whitespace_stripping(): r""" The fancy reports had a bug for a long time where any trailing whitespace on diff --git a/Lib/test/test_doctest/test_doctest2.py b/Lib/test/test_doctest/test_doctest2.py index ea9b430fad80a4..73bc04ba11571c 100644 --- a/Lib/test/test_doctest/test_doctest2.py +++ b/Lib/test/test_doctest/test_doctest2.py @@ -19,6 +19,7 @@ if sys.flags.optimize >= 2: raise unittest.SkipTest("Cannot test docstrings with -O2") + class C(object): """Class C.