From a66adb1c32a4b2960f3d58874e0a0fa0b8a3d734 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sun, 17 Apr 2022 03:09:11 +0900 Subject: [PATCH] Fix #10305: autodoc: Failed to extract optional forwardrefs Autodoc fails to extract optional forwardrefs (ex. `Optional[MyClass]`) even if `MyClass` is declared in `autodoc_type_aliases`. --- CHANGES | 2 ++ sphinx/util/inspect.py | 6 ++++++ .../target/autodoc_type_aliases.py | 5 ++++- tests/test_ext_autodoc_configs.py | 14 ++++++++++++++ tests/test_util_inspect.py | 12 +++++++++++- 5 files changed, 37 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 9aab021a143..3f94098e9b0 100644 --- a/CHANGES +++ b/CHANGES @@ -79,6 +79,8 @@ Bugs fixed mixture of keyword only arguments with/without defaults * #10310: autodoc: class methods are not documented when decorated with mocked function +* #10305: autodoc: Failed to extract optional forward-ref'ed typehints correctly + via :confval:`autodoc_type_aliases` * #10214: html: invalid language tag was generated if :confval:`language` contains a country code (ex. zh_CN) * #10236: html search: objects are duplicated in search result diff --git a/sphinx/util/inspect.py b/sphinx/util/inspect.py index cdcf769650e..b25a75fb50a 100644 --- a/sphinx/util/inspect.py +++ b/sphinx/util/inspect.py @@ -487,6 +487,12 @@ def __call__(self) -> None: def __eq__(self, other: Any) -> bool: return self.name == other + def __hash__(self) -> int: + return hash(self.name) + + def __repr__(self) -> str: + return self.name + class TypeAliasModule: """Pseudo module class for autodoc_type_aliases.""" diff --git a/tests/roots/test-ext-autodoc/target/autodoc_type_aliases.py b/tests/roots/test-ext-autodoc/target/autodoc_type_aliases.py index d8a2fecefce..f2c07a0c7cc 100644 --- a/tests/roots/test-ext-autodoc/target/autodoc_type_aliases.py +++ b/tests/roots/test-ext-autodoc/target/autodoc_type_aliases.py @@ -1,7 +1,7 @@ from __future__ import annotations import io -from typing import overload +from typing import Optional, overload myint = int @@ -11,6 +11,9 @@ #: docstring variable2 = None # type: myint +#: docstring +variable3: Optional[myint] + def read(r: io.BytesIO) -> io.StringIO: """docstring""" diff --git a/tests/test_ext_autodoc_configs.py b/tests/test_ext_autodoc_configs.py index ff4d714c3de..c23afa577b7 100644 --- a/tests/test_ext_autodoc_configs.py +++ b/tests/test_ext_autodoc_configs.py @@ -1144,6 +1144,13 @@ def test_autodoc_type_aliases(app): '', ' docstring', '', + '', + '.. py:data:: variable3', + ' :module: target.autodoc_type_aliases', + ' :type: Optional[int]', + '', + ' docstring', + '', ] # define aliases @@ -1208,6 +1215,13 @@ def test_autodoc_type_aliases(app): '', ' docstring', '', + '', + '.. py:data:: variable3', + ' :module: target.autodoc_type_aliases', + ' :type: Optional[myint]', + '', + ' docstring', + '', ] diff --git a/tests/test_util_inspect.py b/tests/test_util_inspect.py index 5840e9d1ec2..e84e32adfcf 100644 --- a/tests/test_util_inspect.py +++ b/tests/test_util_inspect.py @@ -7,11 +7,21 @@ import sys import types from inspect import Parameter +from typing import Optional import pytest from sphinx.util import inspect -from sphinx.util.inspect import TypeAliasNamespace, stringify_signature +from sphinx.util.inspect import TypeAliasForwardRef, TypeAliasNamespace, stringify_signature +from sphinx.util.typing import stringify + + +def test_TypeAliasForwardRef(): + alias = TypeAliasForwardRef('example') + assert stringify(alias) == 'example' + + alias = Optional[alias] + assert stringify(alias) == 'Optional[example]' def test_TypeAliasNamespace():