From 57dd9ee59452b511162322b41df8c2686c6b4fdf Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Fri, 20 Jan 2023 11:17:46 -0800 Subject: [PATCH 1/2] Fix napoleon handling of numpy docstrings with no explicitly provided return type If there is no explicitly provided return type, napoleon will incorrectly parse the entire return type explanation. It can be fixed by inserting a line with a single colon at the beginning of the returns section. --- src/sphinx_autodoc_typehints/__init__.py | 42 +++++++++++++++++ tests/test_integration.py | 58 ++++++++++++++++++++++++ whitelist.txt | 4 ++ 3 files changed, 104 insertions(+) diff --git a/src/sphinx_autodoc_typehints/__init__.py b/src/sphinx_autodoc_typehints/__init__.py index 9185819f..4a2bbeef 100644 --- a/src/sphinx_autodoc_typehints/__init__.py +++ b/src/sphinx_autodoc_typehints/__init__.py @@ -809,6 +809,44 @@ def fix_autodoc_typehints_for_overloaded_methods() -> None: del MethodDocumenter.format_signature +def napoleon_numpy_docstring_return_type_processor( + app: Sphinx, what: str, name: str, obj: Any, options: Options | None, lines: list[str] # noqa: U100 +) -> None: + """Insert a : under Returns: to tell napoleon not to look for a return type.""" + if what not in ["function", "method"]: + return + if not getattr(app.config, "napoleon_numpy_docstring", False): + return + + # Search for the returns header: + # Returns: + # -------- + for idx, line in enumerate(lines[:-2]): + if line.lower().strip(":") not in ["return", "returns"]: + continue + # Underline detection. + chars = set(lines[idx + 1].strip()) + # Napoleon allows the underline to consist of a bunch of weirder things... + if len(chars) != 1 or list(chars)[0] not in "=-~_*+#": + continue + idx = idx + 2 + break + else: + return + + lines.insert(idx, ":") + + +def fix_napoleon_numpy_docstring_return_type(app: Sphinx) -> None: + """ + If no return type is explicitly provided, numpy docstrings will mess up and + use the return type text as return types. + """ + # standard priority is 500. Setting priority to 499 ensures this runs before + # napoleon's docstring processor. + app.connect("autodoc-process-docstring", napoleon_numpy_docstring_return_type_processor, priority=499) + + def patched_lookup_annotation(*_args: Any) -> str: # noqa: U101 """GoogleDocstring._lookup_annotation sometimes adds incorrect type annotations to constructor parameters (and otherwise does nothing). Disable @@ -818,6 +856,9 @@ def patched_lookup_annotation(*_args: Any) -> str: # noqa: U101 def patch_google_docstring_lookup_annotation() -> None: + """Fix issue 308: + https://github.com/tox-dev/sphinx-autodoc-typehints/issues/308 + """ GoogleDocstring._lookup_annotation = patched_lookup_annotation # type: ignore[assignment] @@ -837,6 +878,7 @@ def setup(app: Sphinx) -> dict[str, bool]: fix_autodoc_typehints_for_overloaded_methods() patch_attribute_handling(app) patch_google_docstring_lookup_annotation() + fix_napoleon_numpy_docstring_return_type(app) return {"parallel_read_safe": True} diff --git a/tests/test_integration.py b/tests/test_integration.py index b1d614ea..04130224 100644 --- a/tests/test_integration.py +++ b/tests/test_integration.py @@ -941,6 +941,64 @@ def __init__(self, blah: CodeType): # noqa: U100 """Description of attribute blah""" +@expected( + """ + mod.napoleon_returns() + + A function. + + Return type: + "CodeType" + + Returns: + The info about the whatever. + """ +) +def napoleon_returns() -> CodeType: + """ + A function. + + Returns + ------- + The info about the whatever. + """ + + +@expected( + """ + mod.google_docstrings(arg1, arg2) + + Summary line. + + Extended description of function. + + Parameters: + * **arg1** ("CodeType") -- Description of arg1 + + * **arg2** ("ModuleType") -- Description of arg2 + + Return type: + "CodeType" + + Returns: + Description of return value + + """ +) +def google_docstrings(arg1: CodeType, arg2: ModuleType) -> CodeType: # noqa: U100 + """Summary line. + + Extended description of function. + + Args: + arg1: Description of arg1 + arg2: Description of arg2 + + Returns: + Description of return value + """ + + AUTO_FUNCTION = ".. autofunction:: mod.{}" AUTO_CLASS = """\ .. autoclass:: mod.{} diff --git a/whitelist.txt b/whitelist.txt index 0ef2f946..7a2e21de 100644 --- a/whitelist.txt +++ b/whitelist.txt @@ -1,4 +1,6 @@ addnodes +arg1 +arg2 ast3 astext autodoc @@ -14,6 +16,7 @@ delattr desc dirname docnames +docstrings Documenter docutils dunder @@ -41,6 +44,7 @@ metaclass ModuleType multiline newtype +numpy nptyping param parametrized From 175ebebb5c48adccaf0a6b156ab5d19a77ad92eb Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Fri, 20 Jan 2023 11:30:52 -0800 Subject: [PATCH 2/2] changelog --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cf8871fa..d8f48312 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## 1.21.7 + +- Fixed a bug where if a class has an attribute and a constructor argument with the same name, the constructor argument + type would be rendered incorrectly (issue 308) + +- Fixed napoleon handling of numpy docstrings with no specified return type. + ## 1.21.6 - Fix a `Field list ends without a blank line` warning (issue 305).