diff --git a/Lib/doctest.py b/Lib/doctest.py index 114aac62a34e95..81ff4b6836a447 100644 --- a/Lib/doctest.py +++ b/Lib/doctest.py @@ -1040,7 +1040,7 @@ def _find(self, tests, obj, name, module, source_lines, globs, seen): # Look for tests in a module's __test__ dictionary. if inspect.ismodule(obj) and self._recurse: - for valname, val in getattr(obj, '__test__', {}).items(): + for valname, val in (getattr(obj, '__test__', None) or {}).items(): if not isinstance(valname, str): raise ValueError("DocTestFinder.find: __test__ keys " "must be strings: %r" % diff --git a/Lib/test/test_doctest.py b/Lib/test/test_doctest.py index 46a51007f9644d..f82478ed984569 100644 --- a/Lib/test/test_doctest.py +++ b/Lib/test/test_doctest.py @@ -597,6 +597,24 @@ def basics(): r""" 2 some_module.__test__.d 1 some_module.sample_func +When ``__test__`` is falsy, this value should be ignored: + + >>> import types + >>> m = types.ModuleType('falsy_magic_test') + >>> m.__dict__.update({'__test__': None}) + + >>> finder = doctest.DocTestFinder() + >>> # Use module=test.test_doctest, to prevent doctest from + >>> # ignoring the objects since they weren't defined in m. + >>> import test.test_doctest + >>> finder.find(m, module=test.test_doctest) + [] + + >>> m.__dict__.update({'__test__': False}) + >>> finder.find(m, module=test.test_doctest) + [] + + Duplicate Removal ~~~~~~~~~~~~~~~~~ If a single object is listed twice (under different names), then tests diff --git a/Misc/NEWS.d/next/Library/2023-12-22-10-56-02.gh-issue-113360.vFD6x5.rst b/Misc/NEWS.d/next/Library/2023-12-22-10-56-02.gh-issue-113360.vFD6x5.rst new file mode 100644 index 00000000000000..272d8999095381 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-22-10-56-02.gh-issue-113360.vFD6x5.rst @@ -0,0 +1 @@ +Fix doctest failure when ``__test__`` magic var is set to a falsy value.