bpo-35753: fix doctest on unwrappables funcs 3/3
Summary: 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. This commit adds the fix to the module. We simply skip any object that throws this exception. This should handle the majority of cases. Future thoughts: 1. Should catching this be optional defaulting to true, but allowing for folks to rethrow the exception to insist on truly clean code? 2. Should we break out _find() into more sub functions sp that we can more easily derive our own versions for each sub function that _find does making it easier to fix future issues? 3. Should we include a way to denylist by `id` some objects so that future objects that cause problems with doctest can be passed in to ignore? Test Plan: Reviewers:
This commit is contained in:
parent
5b83576376
commit
81e0d99c6d
|
@ -976,6 +976,17 @@ class DocTestFinder:
|
||||||
else:
|
else:
|
||||||
raise ValueError("object must be a class or function")
|
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):
|
def _find(self, tests, obj, name, module, source_lines, globs, seen):
|
||||||
"""
|
"""
|
||||||
Find tests for the given object and any contained objects, and
|
Find tests for the given object and any contained objects, and
|
||||||
|
@ -998,9 +1009,9 @@ class DocTestFinder:
|
||||||
if inspect.ismodule(obj) and self._recurse:
|
if inspect.ismodule(obj) and self._recurse:
|
||||||
for valname, val in obj.__dict__.items():
|
for valname, val in obj.__dict__.items():
|
||||||
valname = '%s.%s' % (name, valname)
|
valname = '%s.%s' % (name, valname)
|
||||||
|
|
||||||
# Recurse to functions & classes.
|
# Recurse to functions & classes.
|
||||||
if ((inspect.isroutine(inspect.unwrap(val))
|
if ((self._is_routine(val) or inspect.isclass(val)) and
|
||||||
or inspect.isclass(val)) and
|
|
||||||
self._from_module(module, val)):
|
self._from_module(module, val)):
|
||||||
self._find(tests, val, valname, module, source_lines,
|
self._find(tests, val, valname, module, source_lines,
|
||||||
globs, seen)
|
globs, seen)
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Fix crash in doctest when doctest parses modules that include unwrappable
|
||||||
|
functions by skipping those functions.
|
Loading…
Reference in New Issue