From c16a71c0aa1223731fe0f47ed007ad0a597b3da7 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sun, 15 Nov 2020 13:58:12 +0900 Subject: [PATCH] autodoc: an imported TypeVar is not resolved (refs: #8415) So far, a TypeVar is rendered without module name. As a result, it could not be resolved if it is imported from other modules. This prepends its module name and make it resolvable. This is available only in Python 3.7 or above. As a side effect, all of TypeVars are displayed with module name. It should be fixed in latter step (refs: #7119) --- CHANGES | 2 ++ sphinx/util/typing.py | 5 ++++- tests/test_util_inspect.py | 6 +++++- tests/test_util_typing.py | 14 ++++++++++---- 4 files changed, 21 insertions(+), 6 deletions(-) diff --git a/CHANGES b/CHANGES index a55a4368795..570a550e963 100644 --- a/CHANGES +++ b/CHANGES @@ -27,6 +27,8 @@ Features added * autodoc: Add ``Documenter.config`` as a shortcut to access the config object * autodoc: Add Optional[t] to annotation of function and method if a default value equal to None is set. +* #8415: autodoc: a TypeVar imported from other module is not resolved (in + Python 3.7 or above) * #6914: Add a new event :event:`warn-missing-reference` to custom warning messages when failed to resolve a cross-reference * #6914: Emit a detailed warning when failed to resolve a ``:ref:`` reference diff --git a/sphinx/util/typing.py b/sphinx/util/typing.py index 28f9c5e383d..8f48073dca0 100644 --- a/sphinx/util/typing.py +++ b/sphinx/util/typing.py @@ -261,7 +261,10 @@ def stringify(annotation: Any) -> str: else: return annotation elif isinstance(annotation, TypeVar): - return annotation.__name__ + if annotation.__module__ == 'typing': + return annotation.__name__ + else: + return '.'.join([annotation.__module__, annotation.__name__]) elif not annotation: return repr(annotation) elif annotation is NoneType: diff --git a/tests/test_util_inspect.py b/tests/test_util_inspect.py index 7b51cb7d136..82dc85c007c 100644 --- a/tests/test_util_inspect.py +++ b/tests/test_util_inspect.py @@ -142,7 +142,11 @@ def test_signature_annotations(): # TypeVars and generic types with TypeVars sig = inspect.signature(f2) - assert stringify_signature(sig) == '(x: List[T], y: List[T_co], z: T) -> List[T_contra]' + if sys.version_info < (3, 7): + assert stringify_signature(sig) == '(x: List[T], y: List[T_co], z: T) -> List[T_contra]' + else: + assert stringify_signature(sig) == ('(x: List[typing_test_data.T], y: List[typing_test_data.T_co], ' + 'z: typing_test_data.T) -> List[typing_test_data.T_contra]') # Union types sig = inspect.signature(f3) diff --git a/tests/test_util_typing.py b/tests/test_util_typing.py index 354db15671a..f270a394623 100644 --- a/tests/test_util_typing.py +++ b/tests/test_util_typing.py @@ -174,10 +174,16 @@ def test_stringify_type_hints_typevars(): T_co = TypeVar('T_co', covariant=True) T_contra = TypeVar('T_contra', contravariant=True) - assert stringify(T) == "T" - assert stringify(T_co) == "T_co" - assert stringify(T_contra) == "T_contra" - assert stringify(List[T]) == "List[T]" + if sys.version_info < (3, 7): + assert stringify(T) == "T" + assert stringify(T_co) == "T_co" + assert stringify(T_contra) == "T_contra" + assert stringify(List[T]) == "List[T]" + else: + assert stringify(T) == "test_util_typing.T" + assert stringify(T_co) == "test_util_typing.T_co" + assert stringify(T_contra) == "test_util_typing.T_contra" + assert stringify(List[T]) == "List[test_util_typing.T]" def test_stringify_type_hints_custom_class():