Skip to content

Commit 2653e7d

Browse files
authored
NFC: Move patches to a separate file (#314)
* NFC: Move patches to a separate file * Import __anotations__
1 parent 756049d commit 2653e7d

File tree

2 files changed

+98
-83
lines changed

2 files changed

+98
-83
lines changed

src/sphinx_autodoc_typehints/__init__.py

Lines changed: 2 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import types
88
from ast import FunctionDef, Module, stmt
99
from dataclasses import dataclass
10-
from functools import lru_cache
1110
from typing import Any, AnyStr, Callable, ForwardRef, NewType, TypeVar, get_type_hints
1211

1312
from docutils.frontend import OptionParser
@@ -19,12 +18,11 @@
1918
from sphinx.environment import BuildEnvironment
2019
from sphinx.ext.autodoc import Options
2120
from sphinx.ext.autodoc.mock import mock
22-
from sphinx.ext.napoleon.docstring import GoogleDocstring
2321
from sphinx.util import logging
2422
from sphinx.util.inspect import signature as sphinx_signature
2523
from sphinx.util.inspect import stringify_signature
2624

27-
from .attributes_patch import patch_attribute_handling
25+
from .patches import install_patches
2826
from .version import __version__
2927

3028
_LOGGER = logging.getLogger(__name__)
@@ -786,82 +784,6 @@ def validate_config(app: Sphinx, env: BuildEnvironment, docnames: list[str]) ->
786784
raise ValueError(f"typehints_formatter needs to be callable or `None`, not {formatter}")
787785

788786

789-
@lru_cache() # A cute way to make sure the function only runs once.
790-
def fix_autodoc_typehints_for_overloaded_methods() -> None:
791-
"""
792-
sphinx-autodoc-typehints responds to the "autodoc-process-signature" event
793-
to remove types from the signature line of functions.
794-
795-
Normally, `FunctionDocumenter.format_signature` and
796-
`MethodDocumenter.format_signature` call `super().format_signature` which
797-
ends up going to `Documenter.format_signature`, and this last method emits
798-
the `autodoc-process-signature` event. However, if there are overloads,
799-
`FunctionDocumenter.format_signature` does something else and the event
800-
never occurs.
801-
802-
Here we remove this alternative code path by brute force.
803-
804-
See https://github.com/tox-dev/sphinx-autodoc-typehints/issues/296
805-
"""
806-
from sphinx.ext.autodoc import FunctionDocumenter, MethodDocumenter
807-
808-
del FunctionDocumenter.format_signature
809-
del MethodDocumenter.format_signature
810-
811-
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-
850-
def patched_lookup_annotation(*_args: Any) -> str: # noqa: U101
851-
"""GoogleDocstring._lookup_annotation sometimes adds incorrect type
852-
annotations to constructor parameters (and otherwise does nothing). Disable
853-
it so we can handle this on our own.
854-
"""
855-
return ""
856-
857-
858-
def patch_google_docstring_lookup_annotation() -> None:
859-
"""Fix issue 308:
860-
https://github.com/tox-dev/sphinx-autodoc-typehints/issues/308
861-
"""
862-
GoogleDocstring._lookup_annotation = patched_lookup_annotation # type: ignore[assignment]
863-
864-
865787
def setup(app: Sphinx) -> dict[str, bool]:
866788
app.add_config_value("always_document_param_types", False, "html")
867789
app.add_config_value("typehints_fully_qualified", False, "env")
@@ -875,10 +797,7 @@ def setup(app: Sphinx) -> dict[str, bool]:
875797
app.connect("env-before-read-docs", validate_config) # config may be changed after “config-inited” event
876798
app.connect("autodoc-process-signature", process_signature)
877799
app.connect("autodoc-process-docstring", process_docstring)
878-
fix_autodoc_typehints_for_overloaded_methods()
879-
patch_attribute_handling(app)
880-
patch_google_docstring_lookup_annotation()
881-
fix_napoleon_numpy_docstring_return_type(app)
800+
install_patches(app)
882801
return {"parallel_read_safe": True}
883802

884803

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
from __future__ import annotations
2+
3+
from functools import lru_cache
4+
from typing import Any
5+
6+
from sphinx.application import Sphinx
7+
from sphinx.ext.autodoc import Options
8+
from sphinx.ext.napoleon.docstring import GoogleDocstring
9+
10+
from .attributes_patch import patch_attribute_handling
11+
12+
13+
@lru_cache() # A cute way to make sure the function only runs once.
14+
def fix_autodoc_typehints_for_overloaded_methods() -> None:
15+
"""
16+
sphinx-autodoc-typehints responds to the "autodoc-process-signature" event
17+
to remove types from the signature line of functions.
18+
19+
Normally, `FunctionDocumenter.format_signature` and
20+
`MethodDocumenter.format_signature` call `super().format_signature` which
21+
ends up going to `Documenter.format_signature`, and this last method emits
22+
the `autodoc-process-signature` event. However, if there are overloads,
23+
`FunctionDocumenter.format_signature` does something else and the event
24+
never occurs.
25+
26+
Here we remove this alternative code path by brute force.
27+
28+
See https://github.com/tox-dev/sphinx-autodoc-typehints/issues/296
29+
"""
30+
from sphinx.ext.autodoc import FunctionDocumenter, MethodDocumenter
31+
32+
del FunctionDocumenter.format_signature
33+
del MethodDocumenter.format_signature
34+
35+
36+
def napoleon_numpy_docstring_return_type_processor(
37+
app: Sphinx, what: str, name: str, obj: Any, options: Options | None, lines: list[str] # noqa: U100
38+
) -> None:
39+
"""Insert a : under Returns: to tell napoleon not to look for a return type."""
40+
if what not in ["function", "method"]:
41+
return
42+
if not getattr(app.config, "napoleon_numpy_docstring", False):
43+
return
44+
45+
# Search for the returns header:
46+
# Returns:
47+
# --------
48+
for idx, line in enumerate(lines[:-2]):
49+
if line.lower().strip(":") not in ["return", "returns"]:
50+
continue
51+
# Underline detection.
52+
chars = set(lines[idx + 1].strip())
53+
# Napoleon allows the underline to consist of a bunch of weirder things...
54+
if len(chars) != 1 or list(chars)[0] not in "=-~_*+#":
55+
continue
56+
idx = idx + 2
57+
break
58+
else:
59+
return
60+
61+
lines.insert(idx, ":")
62+
63+
64+
def fix_napoleon_numpy_docstring_return_type(app: Sphinx) -> None:
65+
"""
66+
If no return type is explicitly provided, numpy docstrings will mess up and
67+
use the return type text as return types.
68+
"""
69+
# standard priority is 500. Setting priority to 499 ensures this runs before
70+
# napoleon's docstring processor.
71+
app.connect("autodoc-process-docstring", napoleon_numpy_docstring_return_type_processor, priority=499)
72+
73+
74+
def patched_lookup_annotation(*_args: Any) -> str: # noqa: U101
75+
"""GoogleDocstring._lookup_annotation sometimes adds incorrect type
76+
annotations to constructor parameters (and otherwise does nothing). Disable
77+
it so we can handle this on our own.
78+
"""
79+
return ""
80+
81+
82+
def patch_google_docstring_lookup_annotation() -> None:
83+
"""Fix issue 308:
84+
https://github.com/tox-dev/sphinx-autodoc-typehints/issues/308
85+
"""
86+
GoogleDocstring._lookup_annotation = patched_lookup_annotation # type: ignore[assignment]
87+
88+
89+
def install_patches(app):
90+
fix_autodoc_typehints_for_overloaded_methods()
91+
patch_attribute_handling(app)
92+
patch_google_docstring_lookup_annotation()
93+
fix_napoleon_numpy_docstring_return_type(app)
94+
95+
96+
___all__ = ["install_patches"]

0 commit comments

Comments
 (0)