From 793792fafc8c354a870240ab16d299df206e70c4 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Mon, 15 Oct 2018 22:03:56 +0900 Subject: [PATCH] Fix #5480: autodoc: unable to find type hints for unresolvable Forward references --- CHANGES | 1 + sphinx/util/inspect.py | 19 ++++++------------- tests/test_util_inspect.py | 6 +++++- tests/typing_test_data.py | 4 ++++ 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/CHANGES b/CHANGES index 761ed25397b..a902d56d1e7 100644 --- a/CHANGES +++ b/CHANGES @@ -24,6 +24,7 @@ Bugs fixed * #5495: csv-table directive with file option in included file is broken (refs: #4821) * #5498: autodoc: unable to find type hints for a ``functools.partial`` +* #5480: autodoc: unable to find type hints for unresolvable Forward references Testing -------- diff --git a/sphinx/util/inspect.py b/sphinx/util/inspect.py index 6fdbcc12356..f21473cea3b 100644 --- a/sphinx/util/inspect.py +++ b/sphinx/util/inspect.py @@ -358,19 +358,12 @@ def __init__(self, subject, bound_method=False, has_retval=True): self.argspec = getargspec(subject) try: - if ispartial(subject): - # get_type_hints() does not support partial objects - self.annotations = {} # type: Dict[str, Any] - else: - self.annotations = typing.get_type_hints(subject) # type: ignore - except Exception as exc: - if (3, 5, 0) <= sys.version_info < (3, 5, 3) and isinstance(exc, AttributeError): - # python 3.5.2 raises ValueError for classmethod-ized partial objects. - self.annotations = {} - else: - logger.warning('Invalid type annotation found on %r. Ignored: %r', - subject, exc) - self.annotations = {} + self.annotations = typing.get_type_hints(subject) # type: ignore + except Exception: + # get_type_hints() does not support some kind of objects like partial, + # ForwardRef and so on. For them, it raises an exception. In that case, + # we try to build annotations from argspec. + self.annotations = {} if bound_method: # client gives a hint that the subject is a bound method diff --git a/tests/test_util_inspect.py b/tests/test_util_inspect.py index 99033fb6ee8..397560d94ed 100644 --- a/tests/test_util_inspect.py +++ b/tests/test_util_inspect.py @@ -232,7 +232,7 @@ def meth2(self, arg1, arg2): reason='type annotation test is available on py34 or above') def test_Signature_annotations(): from typing_test_data import ( - f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, Node) + f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, Node) # Class annotations sig = inspect.Signature(f0).format_args() @@ -297,6 +297,10 @@ def test_Signature_annotations(): sig = inspect.Signature(f14).format_args() assert sig == '() -> Any' + # ForwardRef + sig = inspect.Signature(f15).format_args() + assert sig == '(x: Unknown, y: int) -> Any' + # type hints by string sig = inspect.Signature(Node.children).format_args() if (3, 5, 0) <= sys.version_info < (3, 5, 3): diff --git a/tests/typing_test_data.py b/tests/typing_test_data.py index 4dc2d06f5db..fb87b645cf0 100644 --- a/tests/typing_test_data.py +++ b/tests/typing_test_data.py @@ -76,6 +76,10 @@ def f14() -> Any: pass +def f15(x: "Unknown", y: "int") -> Any: + pass + + class Node: def __init__(self, parent: Optional['Node']) -> None: pass