diff -r af18829a7754 Doc/library/doctest.rst --- a/Doc/library/doctest.rst Wed Jul 17 01:22:45 2013 +0200 +++ b/Doc/library/doctest.rst Tue Jul 16 23:30:01 2013 -0500 @@ -278,6 +278,9 @@ Any classes found are recursively searched similarly, to test docstrings in their contained methods and nested classes. +.. versionchanged:: 3.4 + Extension modules are now fully searched as well. + .. _doctest-finding-examples: @@ -1286,8 +1289,8 @@ A processing class used to extract the :class:`DocTest`\ s that are relevant to a given object, from its docstring and the docstrings of its contained objects. :class:`DocTest`\ s can currently be extracted from the following object types: - modules, functions, classes, methods, staticmethods, classmethods, and - properties. + modules, functions, built-in functions, classes, methods, method descriptors + (built-in methods), staticmethods, classmethods, and properties. The optional argument *verbose* can be used to display the objects searched by the finder. It defaults to ``False`` (no output). @@ -1341,6 +1344,11 @@ specified, or ``{}`` otherwise. If *extraglobs* is not specified, then it defaults to ``{}``. + .. versionchanged:: 3.4 + :class:`DocTestFinder` can now find doctests in the docstrings of + built-in functions and methods. + + .. _doctest-doctestparser: diff -r af18829a7754 Lib/doctest.py --- a/Lib/doctest.py Wed Jul 17 01:22:45 2013 +0200 +++ b/Lib/doctest.py Tue Jul 16 23:30:01 2013 -0500 @@ -918,6 +918,8 @@ return module is inspect.getmodule(object) elif inspect.isfunction(object): return module.__dict__ is object.__globals__ + elif inspect.ismethoddescriptor(object): + return module.__name__ == object.__objclass__.__module__ elif inspect.isclass(object): return module.__name__ == object.__module__ elif hasattr(object, '__module__'): @@ -950,7 +952,7 @@ for valname, val in obj.__dict__.items(): valname = '%s.%s' % (name, valname) # Recurse to functions & classes. - if ((inspect.isfunction(val) or inspect.isclass(val)) and + if ((inspect.isroutine(val) or inspect.isclass(val)) and self._from_module(module, val)): self._find(tests, val, valname, module, source_lines, globs, seen) @@ -962,9 +964,8 @@ raise ValueError("DocTestFinder.find: __test__ keys " "must be strings: %r" % (type(valname),)) - if not (inspect.isfunction(val) or inspect.isclass(val) or - inspect.ismethod(val) or inspect.ismodule(val) or - isinstance(val, str)): + if not (inspect.isroutine(val) or inspect.isclass(val) or + inspect.ismodule(val) or isinstance(val, str)): raise ValueError("DocTestFinder.find: __test__ values " "must be strings, functions, methods, " "classes, or modules: %r" % @@ -983,7 +984,7 @@ val = getattr(obj, valname).__func__ # Recurse to methods, properties, and nested classes. - if ((inspect.isfunction(val) or inspect.isclass(val) or + if ((inspect.isroutine(val) or inspect.isclass(val) or isinstance(val, property)) and self._from_module(module, val)): valname = '%s.%s' % (name, valname) diff -r af18829a7754 Lib/test/test_builtin.py --- a/Lib/test/test_builtin.py Wed Jul 17 01:22:45 2013 +0200 +++ b/Lib/test/test_builtin.py Tue Jul 16 23:30:01 2013 -0500 @@ -1595,21 +1595,10 @@ data = 'The quick Brown fox Jumped over The lazy Dog'.split() self.assertRaises(TypeError, sorted, data, None, lambda x,y: 0) -def test_main(verbose=None): - test_classes = (BuiltinTest, TestSorted) - - run_unittest(*test_classes) - - # verify reference counting - if verbose and hasattr(sys, "gettotalrefcount"): - import gc - counts = [None] * 5 - for i in range(len(counts)): - run_unittest(*test_classes) - gc.collect() - counts[i] = sys.gettotalrefcount() - print(counts) - +def load_tests(loader, tests, pattern): + from doctest import DocTestSuite + tests.addTest(DocTestSuite(builtins)) + return tests if __name__ == "__main__": - test_main(verbose=True) + unittest.main() diff -r af18829a7754 Lib/test/test_doctest.py --- a/Lib/test/test_doctest.py Wed Jul 17 01:22:45 2013 +0200 +++ b/Lib/test/test_doctest.py Tue Jul 16 23:30:01 2013 -0500 @@ -644,6 +644,31 @@ >>> test = doctest.DocTestFinder().find(f)[0] >>> [e.lineno for e in test.examples] [1, 9, 12] + +Finding Doctests in Extension Modules +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +DocTestFinder can also find doctests in extension modules. builtins isn't +really an extension module, but it's written in C and guaranteed to be there, +so we'll use it anyway. + + >>> import builtins + >>> tests = doctest.DocTestFinder().find(builtins) + >>> len(tests) # how many objects checked for doctests + 795 + >>> real_tests = [t for t in tests if len(t.examples) > 0] + >>> len(real_tests) # how many objects actually have doctests + 8 + >>> for t in real_tests: + ... print('{} {}'.format(len(t.examples), t.name)) + ... + 1 builtins.bin + 3 builtins.float.as_integer_ratio + 2 builtins.float.fromhex + 2 builtins.float.hex + 1 builtins.hex + 1 builtins.int + 2 builtins.int.bit_length + 1 builtins.oct """ def test_DocTestParser(): r""" diff -r af18829a7754 Objects/floatobject.c --- a/Objects/floatobject.c Wed Jul 17 01:22:45 2013 +0200 +++ b/Objects/floatobject.c Tue Jul 16 23:30:01 2013 -0500 @@ -1416,7 +1416,7 @@ >>> float.fromhex('0x1.ffffp10')\n\ 2047.984375\n\ >>> float.fromhex('-0x1p-1074')\n\ --4.9406564584124654e-324"); +-5e-324"); static PyObject * diff -r af18829a7754 Python/bltinmodule.c --- a/Python/bltinmodule.c Wed Jul 17 01:22:45 2013 +0200 +++ b/Python/bltinmodule.c Tue Jul 16 23:30:01 2013 -0500 @@ -340,7 +340,11 @@ PyDoc_STRVAR(bin_doc, "bin(number) -> string\n\ \n\ -Return the binary representation of an integer."); +Return the binary representation of an integer.\n\ +\n\ + >>> bin(2796202)\n\ + '0b1010101010101010101010'\n\ +"); static PyObject * @@ -1263,7 +1267,11 @@ PyDoc_STRVAR(hex_doc, "hex(number) -> string\n\ \n\ -Return the hexadecimal representation of an integer."); +Return the hexadecimal representation of an integer.\n\ +\n\ + >>> hex(3735928559)\n\ + '0xdeadbeef'\n\ +"); static PyObject * @@ -1463,7 +1471,11 @@ PyDoc_STRVAR(oct_doc, "oct(number) -> string\n\ \n\ -Return the octal representation of an integer."); +Return the octal representation of an integer.\n\ +\n\ + >>> oct(342391)\n\ + '0o1234567'\n\ +"); static PyObject *