Skip to content

Commit 3aca67b

Browse files
authored
Fix napoleon handling of numpy docstrings with no explicitly provided return type (#311)
1 parent 53f7f00 commit 3aca67b

File tree

4 files changed

+111
-0
lines changed

4 files changed

+111
-0
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# Changelog
22

3+
## 1.21.7
4+
5+
- Fixed a bug where if a class has an attribute and a constructor argument with the same name, the constructor argument
6+
type would be rendered incorrectly (issue 308)
7+
8+
- Fixed napoleon handling of numpy docstrings with no specified return type.
9+
310
## 1.21.6
411

512
- Fix a `Field list ends without a blank line` warning (issue 305).

src/sphinx_autodoc_typehints/__init__.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -809,6 +809,44 @@ def fix_autodoc_typehints_for_overloaded_methods() -> None:
809809
del MethodDocumenter.format_signature
810810

811811

812+
def napoleon_numpy_docstring_return_type_processor(
813+
app: Sphinx, what: str, name: str, obj: Any, options: Options | None, lines: list[str] # noqa: U100
814+
) -> None:
815+
"""Insert a : under Returns: to tell napoleon not to look for a return type."""
816+
if what not in ["function", "method"]:
817+
return
818+
if not getattr(app.config, "napoleon_numpy_docstring", False):
819+
return
820+
821+
# Search for the returns header:
822+
# Returns:
823+
# --------
824+
for idx, line in enumerate(lines[:-2]):
825+
if line.lower().strip(":") not in ["return", "returns"]:
826+
continue
827+
# Underline detection.
828+
chars = set(lines[idx + 1].strip())
829+
# Napoleon allows the underline to consist of a bunch of weirder things...
830+
if len(chars) != 1 or list(chars)[0] not in "=-~_*+#":
831+
continue
832+
idx = idx + 2
833+
break
834+
else:
835+
return
836+
837+
lines.insert(idx, ":")
838+
839+
840+
def fix_napoleon_numpy_docstring_return_type(app: Sphinx) -> None:
841+
"""
842+
If no return type is explicitly provided, numpy docstrings will mess up and
843+
use the return type text as return types.
844+
"""
845+
# standard priority is 500. Setting priority to 499 ensures this runs before
846+
# napoleon's docstring processor.
847+
app.connect("autodoc-process-docstring", napoleon_numpy_docstring_return_type_processor, priority=499)
848+
849+
812850
def patched_lookup_annotation(*_args: Any) -> str: # noqa: U101
813851
"""GoogleDocstring._lookup_annotation sometimes adds incorrect type
814852
annotations to constructor parameters (and otherwise does nothing). Disable
@@ -818,6 +856,9 @@ def patched_lookup_annotation(*_args: Any) -> str: # noqa: U101
818856

819857

820858
def patch_google_docstring_lookup_annotation() -> None:
859+
"""Fix issue 308:
860+
https://github.com/tox-dev/sphinx-autodoc-typehints/issues/308
861+
"""
821862
GoogleDocstring._lookup_annotation = patched_lookup_annotation # type: ignore[assignment]
822863

823864

@@ -837,6 +878,7 @@ def setup(app: Sphinx) -> dict[str, bool]:
837878
fix_autodoc_typehints_for_overloaded_methods()
838879
patch_attribute_handling(app)
839880
patch_google_docstring_lookup_annotation()
881+
fix_napoleon_numpy_docstring_return_type(app)
840882
return {"parallel_read_safe": True}
841883

842884

tests/test_integration.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -941,6 +941,64 @@ def __init__(self, blah: CodeType): # noqa: U100
941941
"""Description of attribute blah"""
942942

943943

944+
@expected(
945+
"""
946+
mod.napoleon_returns()
947+
948+
A function.
949+
950+
Return type:
951+
"CodeType"
952+
953+
Returns:
954+
The info about the whatever.
955+
"""
956+
)
957+
def napoleon_returns() -> CodeType:
958+
"""
959+
A function.
960+
961+
Returns
962+
-------
963+
The info about the whatever.
964+
"""
965+
966+
967+
@expected(
968+
"""
969+
mod.google_docstrings(arg1, arg2)
970+
971+
Summary line.
972+
973+
Extended description of function.
974+
975+
Parameters:
976+
* **arg1** ("CodeType") -- Description of arg1
977+
978+
* **arg2** ("ModuleType") -- Description of arg2
979+
980+
Return type:
981+
"CodeType"
982+
983+
Returns:
984+
Description of return value
985+
986+
"""
987+
)
988+
def google_docstrings(arg1: CodeType, arg2: ModuleType) -> CodeType: # noqa: U100
989+
"""Summary line.
990+
991+
Extended description of function.
992+
993+
Args:
994+
arg1: Description of arg1
995+
arg2: Description of arg2
996+
997+
Returns:
998+
Description of return value
999+
"""
1000+
1001+
9441002
AUTO_FUNCTION = ".. autofunction:: mod.{}"
9451003
AUTO_CLASS = """\
9461004
.. autoclass:: mod.{}

whitelist.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
addnodes
2+
arg1
3+
arg2
24
ast3
35
astext
46
autodoc
@@ -14,6 +16,7 @@ delattr
1416
desc
1517
dirname
1618
docnames
19+
docstrings
1720
Documenter
1821
docutils
1922
dunder
@@ -41,6 +44,7 @@ metaclass
4144
ModuleType
4245
multiline
4346
newtype
47+
numpy
4448
nptyping
4549
param
4650
parametrized

0 commit comments

Comments
 (0)