summaryrefslogtreecommitdiff
path: root/sphinx/util/inspect.py
diff options
context:
space:
mode:
Diffstat (limited to 'sphinx/util/inspect.py')
-rw-r--r--sphinx/util/inspect.py36
1 files changed, 24 insertions, 12 deletions
diff --git a/sphinx/util/inspect.py b/sphinx/util/inspect.py
index 5118ee98c..79efbeaf7 100644
--- a/sphinx/util/inspect.py
+++ b/sphinx/util/inspect.py
@@ -372,27 +372,39 @@ def is_builtin_class_method(obj: Any, attr_name: str) -> bool:
Why this function needed? CPython implements int.__init__ by Descriptor
but PyPy implements it by pure Python code.
"""
- classes = [c for c in inspect.getmro(obj) if attr_name in c.__dict__]
- cls = classes[0] if classes else object
+ try:
+ mro = inspect.getmro(obj)
+ except AttributeError:
+ # no __mro__, assume the object has no methods as we know them
+ return False
- if not hasattr(builtins, safe_getattr(cls, '__name__', '')):
+ try:
+ cls = next(c for c in mro if attr_name in safe_getattr(c, '__dict__', {}))
+ except StopIteration:
return False
- return getattr(builtins, safe_getattr(cls, '__name__', '')) is cls
+
+ try:
+ name = safe_getattr(cls, '__name__')
+ except AttributeError:
+ return False
+
+ return getattr(builtins, name, None) is cls
-def signature(subject: Callable, bound_method: bool = False) -> inspect.Signature:
+def signature(subject: Callable, bound_method: bool = False, follow_wrapped: bool = False
+ ) -> inspect.Signature:
"""Return a Signature object for the given *subject*.
:param bound_method: Specify *subject* is a bound method or not
+ :param follow_wrapped: Same as ``inspect.signature()``.
+ Defaults to ``False`` (get a signature of *subject*).
"""
- # check subject is not a built-in class (ex. int, str)
- if (isinstance(subject, type) and
- is_builtin_class_method(subject, "__new__") and
- is_builtin_class_method(subject, "__init__")):
- raise TypeError("can't compute signature for built-in type {}".format(subject))
-
try:
- signature = inspect.signature(subject)
+ try:
+ signature = inspect.signature(subject, follow_wrapped=follow_wrapped)
+ except ValueError:
+ # follow built-in wrappers up (ex. functools.lru_cache)
+ signature = inspect.signature(subject)
parameters = list(signature.parameters.values())
return_annotation = signature.return_annotation
except IndexError: