Skip to content

Commit ab7a856

Browse files
authored
Fix for sphinx-autodoc-typehints 1.12 (#32)
1 parent f961e7e commit ab7a856

File tree

3 files changed

+43
-17
lines changed

3 files changed

+43
-17
lines changed

pyproject.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ test = [
3131
'typing_extensions; python_version<"3.8"',
3232
]
3333
doc = [
34-
'sphinx-autodoc-typehints>=1.11.1',
34+
'sphinx-autodoc-typehints>=1.12',
3535
'sphinx-rtd-theme',
3636
]
3737

scanpydoc/elegant_typehints/formatting.py

+37-15
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,20 @@
2121
from scanpydoc import elegant_typehints
2222

2323

24-
def _format_full(annotation: Type[Any], fully_qualified: bool = False):
24+
def _format_full(
25+
annotation: Type[Any],
26+
fully_qualified: bool = False,
27+
simplify_optional_unions: bool = True,
28+
):
2529
if inspect.isclass(annotation) and annotation.__module__ == "builtins":
26-
return _format_orig(annotation, fully_qualified)
30+
return _format_orig(annotation, fully_qualified, simplify_optional_unions)
2731

2832
origin = get_origin(annotation)
2933
tilde = "" if fully_qualified else "~"
3034

3135
annotation_cls = annotation if inspect.isclass(annotation) else type(annotation)
3236
if annotation_cls.__module__ == "typing":
33-
return _format_orig(annotation, fully_qualified)
37+
return _format_orig(annotation, fully_qualified, simplify_optional_unions)
3438

3539
# Only if this is a real class we override sphinx_autodoc_typehints
3640
if inspect.isclass(annotation) or inspect.isclass(origin):
@@ -40,14 +44,22 @@ def _format_full(annotation: Type[Any], fully_qualified: bool = False):
4044
if override is not None:
4145
return f":py:{role}:`{tilde}{override}`"
4246

43-
return _format_orig(annotation, fully_qualified)
47+
return _format_orig(annotation, fully_qualified, simplify_optional_unions)
4448

4549

46-
def _format_terse(annotation: Type[Any], fully_qualified: bool = False) -> str:
50+
def _format_terse(
51+
annotation: Type[Any],
52+
fully_qualified: bool = False,
53+
simplify_optional_unions: bool = True,
54+
) -> str:
4755
origin = get_origin(annotation)
4856
args = get_args(annotation)
4957
tilde = "" if fully_qualified else "~"
50-
fmt = partial(_format_terse, fully_qualified=fully_qualified)
58+
fmt = partial(
59+
_format_terse,
60+
fully_qualified=fully_qualified,
61+
simplify_optional_unions=simplify_optional_unions,
62+
)
5163

5264
# display `Union[A, B]` as `A | B`
5365
if origin is Union:
@@ -74,10 +86,14 @@ def _format_terse(annotation: Type[Any], fully_qualified: bool = False) -> str:
7486
if origin is Literal:
7587
return f"{{{', '.join(map(repr, args))}}}"
7688

77-
return _format_full(annotation, fully_qualified)
89+
return _format_full(annotation, fully_qualified, simplify_optional_unions)
7890

7991

80-
def format_annotation(annotation: Type[Any], fully_qualified: bool = False) -> str:
92+
def format_annotation(
93+
annotation: Type[Any],
94+
fully_qualified: bool = False,
95+
simplify_optional_unions: bool = True,
96+
) -> str:
8197
r"""Generate reStructuredText containing links to the types.
8298
8399
Unlike :func:`sphinx_autodoc_typehints.format_annotation`,
@@ -87,6 +103,9 @@ def format_annotation(annotation: Type[Any], fully_qualified: bool = False) -> s
87103
annotation: A type or class used as type annotation.
88104
fully_qualified: If links should be formatted as fully qualified
89105
(e.g. ``:py:class:`foo.Bar```) or not (e.g. ``:py:class:`~foo.Bar```).
106+
simplify_optional_unions: If Unions should be minimized if they contain
107+
3 or more elements one of which is ``None``. (If ``True``, e.g.
108+
``Optional[Union[str, int]]`` becomes ``Union[str, int, None]``)
90109
91110
Returns:
92111
reStructuredText describing the type
@@ -100,7 +119,7 @@ def format_annotation(annotation: Type[Any], fully_qualified: bool = False) -> s
100119
curframe = inspect.currentframe()
101120
calframe = inspect.getouterframes(curframe, 2)
102121
if calframe[1][3] == "process_docstring":
103-
annot_fmt = format_both(annotation, fully_qualified)
122+
annot_fmt = format_both(annotation, fully_qualified, simplify_optional_unions)
104123
if elegant_typehints.annotate_defaults:
105124
variables = calframe[1].frame.f_locals
106125
sig = inspect.signature(variables["obj"])
@@ -111,14 +130,17 @@ def format_annotation(annotation: Type[Any], fully_qualified: bool = False) -> s
111130
annot_fmt += f" (default: ``{_escape(repr(default))}``)"
112131
return annot_fmt
113132
else: # recursive use
114-
return _format_full(annotation, fully_qualified)
133+
return _format_full(annotation, fully_qualified, simplify_optional_unions)
115134

116135

117-
def format_both(annotation: Type[Any], fully_qualified: bool = False):
118-
return (
119-
f":annotation-terse:`{_escape(_format_terse(annotation, fully_qualified))}`\\ "
120-
f":annotation-full:`{_escape(_format_full(annotation, fully_qualified))}`"
121-
)
136+
def format_both(
137+
annotation: Type[Any],
138+
fully_qualified: bool = False,
139+
simplify_optional_unions: bool = True,
140+
) -> str:
141+
terse = _format_terse(annotation, fully_qualified, simplify_optional_unions)
142+
full = _format_full(annotation, fully_qualified, simplify_optional_unions)
143+
return f":annotation-terse:`{_escape(terse)}`\\ :annotation-full:`{_escape(full)}`"
122144

123145

124146
def _role_annot(

tests/test_elegant_typehints.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,11 @@ def test_autodoc(app, _testmod, direc, base, sub):
267267
app.build()
268268
out = Path(app.outdir, "index.html").read_text()
269269
assert not app._warning.getvalue(), app._warning.getvalue()
270-
assert re.search(rf"<code[^>]*>test\.</code><code[^>]*>{sub}</code>", out), out
270+
assert re.search(
271+
r'<code[^>]*><span class="pre">test\.</span></code>'
272+
f'<code[^>]*><span class="pre">{sub}</span></code>',
273+
out,
274+
), out
271275
assert f'<a class="headerlink" href="#test.{sub}"' in out, out
272276
assert re.search(rf"Bases: <code[^>]*><span[^>]*>test\.{base}", out), out
273277

0 commit comments

Comments
 (0)