77from unittest .mock import patch
88
99import sphinx .domains .python
10- import sphinx .ext .autodoc
1110from sphinx .domains .python import PyAttribute
12- from sphinx .ext .autodoc import AttributeDocumenter
1311
1412from ._parser import parse
1513
2119# Defensively check for the things we want to patch
2220_parse_annotation = getattr (sphinx .domains .python , "_parse_annotation" , None )
2321
24- # We want to patch:
25- # * sphinx.ext.autodoc.stringify_typehint (in sphinx < 6.1)
26- # * sphinx.ext.autodoc.stringify_annotation (in sphinx >= 6.1)
27- STRINGIFY_PATCH_TARGET = ""
28- for target in ["stringify_typehint" , "stringify_annotation" ]:
29- if hasattr (sphinx .ext .autodoc , target ):
30- STRINGIFY_PATCH_TARGET = f"sphinx.ext.autodoc.{ target } "
31- break
32-
33- # If we didn't locate both patch targets, we will just do nothing.
34- OKAY_TO_PATCH = bool (_parse_annotation and STRINGIFY_PATCH_TARGET )
22+ # If we didn't locate the patch target, we will just do nothing.
23+ OKAY_TO_PATCH = bool (_parse_annotation )
3524
3625# A label we inject to the type string so we know not to try to treat it as a
3726# type annotation
3827TYPE_IS_RST_LABEL = "--is-rst--"
3928
40-
41- orig_add_directive_header = AttributeDocumenter .add_directive_header
4229orig_handle_signature = PyAttribute .handle_signature
4330
4431
45- def _stringify_annotation (app : Sphinx , annotation : Any , * args : Any , short_literals : bool = False , ** kwargs : Any ) -> str : # noqa: ARG001
46- # Format the annotation with sphinx-autodoc-typehints and inject our magic prefix to tell our patched
47- # PyAttribute.handle_signature to treat it as rst.
48- from . import format_annotation # noqa: PLC0415
49-
50- return TYPE_IS_RST_LABEL + format_annotation (annotation , app .config , short_literals = short_literals )
51-
52-
53- def patch_attribute_documenter (app : Sphinx ) -> None :
54- """Instead of using stringify_typehint in `AttributeDocumenter.add_directive_header`, use `format_annotation`."""
55-
56- def add_directive_header (* args : Any , ** kwargs : Any ) -> Any :
57- with patch (STRINGIFY_PATCH_TARGET , partial (_stringify_annotation , app )):
58- return orig_add_directive_header (* args , ** kwargs )
59-
60- AttributeDocumenter .add_directive_header = add_directive_header # type:ignore[method-assign]
61-
62-
6332def rst_to_docutils (settings : Values , rst : str ) -> Any :
6433 """Convert rst to a sequence of docutils nodes."""
6534 doc = parse (rst , settings )
@@ -84,12 +53,11 @@ def patched_handle_signature(self: PyAttribute, sig: str, signode: desc_signatur
8453 return orig_handle_signature (self , sig , signode )
8554
8655
87- def patch_attribute_handling (app : Sphinx ) -> None :
88- """Use format_signature to format class attribute type annotations."""
56+ def patch_attribute_handling (app : Sphinx ) -> None : # noqa: ARG001
57+ """Patch PyAttribute.handle_signature to format class attribute type annotations."""
8958 if not OKAY_TO_PATCH :
9059 return
9160 PyAttribute .handle_signature = patched_handle_signature # type:ignore[method-assign]
92- patch_attribute_documenter (app )
9361
9462
9563__all__ = ["patch_attribute_handling" ]
0 commit comments