Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix napoleon handling of numpy docstrings with no explicitly provided return type #311

Merged
merged 2 commits into from Jan 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 7 additions & 0 deletions 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).
Expand Down
42 changes: 42 additions & 0 deletions src/sphinx_autodoc_typehints/__init__.py
Expand Up @@ -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
Expand All @@ -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]


Expand All @@ -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}


Expand Down
58 changes: 58 additions & 0 deletions tests/test_integration.py
Expand Up @@ -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.{}
Expand Down
4 changes: 4 additions & 0 deletions whitelist.txt
@@ -1,4 +1,6 @@
addnodes
arg1
arg2
ast3
astext
autodoc
Expand All @@ -14,6 +16,7 @@ delattr
desc
dirname
docnames
docstrings
Documenter
docutils
dunder
Expand Down Expand Up @@ -41,6 +44,7 @@ metaclass
ModuleType
multiline
newtype
numpy
nptyping
param
parametrized
Expand Down