summaryrefslogtreecommitdiffstats
path: root/Lib/doctest.py
diff options
context:
space:
mode:
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>2021-05-05 18:01:21 (GMT)
committerGitHub <noreply@github.com>2021-05-05 18:01:21 (GMT)
commit10d6f6bfd749c0e7da51a96f53ca326c336f7a00 (patch)
treeae5dc9e22210b4a6c2d65c2e2556fa9e6ed900be /Lib/doctest.py
parentce4fee210bb604726e5da0ff15952a60c2098f88 (diff)
downloadcpython-10d6f6bfd749c0e7da51a96f53ca326c336f7a00.zip
cpython-10d6f6bfd749c0e7da51a96f53ca326c336f7a00.tar.gz
cpython-10d6f6bfd749c0e7da51a96f53ca326c336f7a00.tar.bz2
bpo-35753: Fix crash in doctest with unwrap-able functions (GH-22981) (#25926)
Ignore objects that inspect.unwrap throws due to too many wrappers. This is a very rare case, however it can easily be surfaced when a module under doctest imports unitest.mock.call into its namespace. We simply skip any object that throws this exception. This should handle the majority of cases. (cherry picked from commit 565a31804c1139fe7886f38af3b3923653b0c1b3) Co-authored-by: Alfred Perlstein <alfred@fb.com>
Diffstat (limited to 'Lib/doctest.py')
-rw-r--r--Lib/doctest.py15
1 files changed, 13 insertions, 2 deletions
diff --git a/Lib/doctest.py b/Lib/doctest.py
index e95c333..ba898f6 100644
--- a/Lib/doctest.py
+++ b/Lib/doctest.py
@@ -973,6 +973,17 @@ class DocTestFinder:
else:
raise ValueError("object must be a class or function")
+ def _is_routine(self, obj):
+ """
+ Safely unwrap objects and determine if they are functions.
+ """
+ maybe_routine = obj
+ try:
+ maybe_routine = inspect.unwrap(maybe_routine)
+ except ValueError:
+ pass
+ return inspect.isroutine(maybe_routine)
+
def _find(self, tests, obj, name, module, source_lines, globs, seen):
"""
Find tests for the given object and any contained objects, and
@@ -995,9 +1006,9 @@ class DocTestFinder:
if inspect.ismodule(obj) and self._recurse:
for valname, val in obj.__dict__.items():
valname = '%s.%s' % (name, valname)
+
# Recurse to functions & classes.
- if ((inspect.isroutine(inspect.unwrap(val))
- or inspect.isclass(val)) and
+ if ((self._is_routine(val) or inspect.isclass(val)) and
self._from_module(module, val)):
self._find(tests, val, valname, module, source_lines,
globs, seen)