diff --git a/CHANGES b/CHANGES index 34e651241de..a7950b8e041 100644 --- a/CHANGES +++ b/CHANGES @@ -18,6 +18,7 @@ Bugs fixed * #7428: py domain: a reference to class ``None`` emits a nitpicky warning * #7438: C++, fix merging overloaded functions in parallel builds. +* #7422: autodoc: fails with ValueError when using autodoc_mock_imports Testing -------- diff --git a/sphinx/util/inspect.py b/sphinx/util/inspect.py index 570ea9df677..64c1568f61c 100644 --- a/sphinx/util/inspect.py +++ b/sphinx/util/inspect.py @@ -17,7 +17,7 @@ import warnings from functools import partial, partialmethod from inspect import ( # NOQA - Parameter, isclass, ismethod, ismethoddescriptor, unwrap + Parameter, isclass, ismethod, ismethoddescriptor ) from io import StringIO from typing import Any, Callable, Mapping, List, Tuple @@ -116,6 +116,15 @@ def getargspec(func: Callable) -> Any: kwonlyargs, kwdefaults, annotations) +def unwrap(obj: Any) -> Any: + """Get an original object from wrapped object (wrapped functions).""" + try: + return inspect.unwrap(obj) + except ValueError: + # might be a mock object + return obj + + def unwrap_all(obj: Any) -> Any: """ Get an original object from wrapped object (unwrapping partials, wrapped @@ -217,7 +226,7 @@ def isattributedescriptor(obj: Any) -> bool: return True elif isdescriptor(obj): # non data descriptor - unwrapped = inspect.unwrap(obj) + unwrapped = unwrap(obj) if isfunction(unwrapped) or isbuiltin(unwrapped) or inspect.ismethod(unwrapped): # attribute must not be either function, builtin and method return False