diff options
| author | Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com> | 2021-05-05 18:01:21 (GMT) |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-05-05 18:01:21 (GMT) |
| commit | 10d6f6bfd749c0e7da51a96f53ca326c336f7a00 (patch) | |
| tree | ae5dc9e22210b4a6c2d65c2e2556fa9e6ed900be /Lib/doctest.py | |
| parent | ce4fee210bb604726e5da0ff15952a60c2098f88 (diff) | |
| download | cpython-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.py | 15 |
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) |
