From 6d1cafe7bd0ec10f453952b51aff80eb6f44c7b0 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sun, 8 Nov 2020 13:17:28 +0900 Subject: [PATCH] autodoc: Add Optional[t] to annotation of function and method As typing.get_type_hints() doing, this adds Optional[t] to type annotations if a default value equal to None is set. Note: this is default behavior of inspect.signature() since Python 3.10. --- CHANGES | 2 ++ sphinx/util/inspect.py | 4 ++-- tests/test_ext_autodoc_configs.py | 2 +- tests/test_util_inspect.py | 6 +++--- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/CHANGES b/CHANGES index 360d17794..53990bb7b 100644 --- a/CHANGES +++ b/CHANGES @@ -22,6 +22,8 @@ Features added ``__all__`` attribute of the module should be documented or not via :event:`autodoc-skip-member` event * 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. * #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/inspect.py b/sphinx/util/inspect.py index 1eaccb678..92c6ac7fb 100644 --- a/sphinx/util/inspect.py +++ b/sphinx/util/inspect.py @@ -470,10 +470,10 @@ def signature(subject: Callable, bound_method: bool = False, follow_wrapped: boo raise try: - # Update unresolved annotations using ``get_type_hints()``. + # Resolve forwared reference annotations using ``get_type_hints()`` and type_aliases. annotations = typing.get_type_hints(subject, None, type_aliases) for i, param in enumerate(parameters): - if isinstance(param.annotation, str) and param.name in annotations: + if param.name in annotations: parameters[i] = param.replace(annotation=annotations[param.name]) if 'return' in annotations: return_annotation = annotations['return'] diff --git a/tests/test_ext_autodoc_configs.py b/tests/test_ext_autodoc_configs.py index a0eba20c8..19936c5ae 100644 --- a/tests/test_ext_autodoc_configs.py +++ b/tests/test_ext_autodoc_configs.py @@ -490,7 +490,7 @@ def test_autodoc_typehints_signature(app): '.. py:module:: target.typehints', '', '', - '.. py:class:: Math(s: str, o: Any = None)', + '.. py:class:: Math(s: str, o: Optional[Any] = None)', ' :module: target.typehints', '', '', diff --git a/tests/test_util_inspect.py b/tests/test_util_inspect.py index 204fa65b7..8726544a6 100644 --- a/tests/test_util_inspect.py +++ b/tests/test_util_inspect.py @@ -162,7 +162,7 @@ def test_signature_annotations(): # Space around '=' for defaults sig = inspect.signature(f7) - assert stringify_signature(sig) == '(x: int = None, y: dict = {}) -> None' + assert stringify_signature(sig) == '(x: Optional[int] = None, y: dict = {}) -> None' # Callable types sig = inspect.signature(f8) @@ -226,7 +226,7 @@ def test_signature_annotations(): assert stringify_signature(sig) == '(self) -> List[typing_test_data.Node]' sig = inspect.signature(Node.__init__) - assert stringify_signature(sig) == '(self, parent: Optional[Node]) -> None' + assert stringify_signature(sig) == '(self, parent: Optional[typing_test_data.Node]) -> None' # show_annotation is False sig = inspect.signature(f7) @@ -234,7 +234,7 @@ def test_signature_annotations(): # show_return_annotation is False sig = inspect.signature(f7) - assert stringify_signature(sig, show_return_annotation=False) == '(x: int = None, y: dict = {})' + assert stringify_signature(sig, show_return_annotation=False) == '(x: Optional[int] = None, y: dict = {})' @pytest.mark.skipif(sys.version_info < (3, 8), reason='python 3.8+ is required.')