Skip to content

Commit 0435d07

Browse files
Fix issue #462 and another alias processing bug (#463)
* test update (non-reproducible) * fix candidate #1 * fixes issue #462 * Fix annotation check exception (#462) Fix processing type aliases * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * reverted test_integration.py * make _SchemaMeta hashable for ruff pre-commit test * pre-commit ci fix try no 2 * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * _get_type_hint(): fixed the type hint of localns arg --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent fb240ea commit 0435d07

File tree

2 files changed

+83
-22
lines changed

2 files changed

+83
-22
lines changed

src/sphinx_autodoc_typehints/__init__.py

+16-11
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
from sphinx.ext.autodoc.mock import mock
1818
from sphinx.parsers import RSTParser
1919
from sphinx.util import logging, rst
20+
from sphinx.util.inspect import TypeAliasForwardRef, TypeAliasNamespace, stringify_signature
2021
from sphinx.util.inspect import signature as sphinx_signature
21-
from sphinx.util.inspect import stringify_signature
2222

2323
from .parser import parse
2424
from .patches import install_patches
@@ -194,6 +194,9 @@ def format_annotation(annotation: Any, config: Config) -> str: # noqa: C901, PL
194194
if isinstance(annotation, tuple):
195195
return format_internal_tuple(annotation, config)
196196

197+
if isinstance(annotation, TypeAliasForwardRef):
198+
return str(annotation)
199+
197200
try:
198201
module = get_annotation_module(annotation)
199202
class_name = get_annotation_class_name(annotation, module)
@@ -404,16 +407,18 @@ def _future_annotations_imported(obj: Any) -> bool:
404407
return bool(_annotations.compiler_flag == future_annotations)
405408

406409

407-
def get_all_type_hints(autodoc_mock_imports: list[str], obj: Any, name: str) -> dict[str, Any]:
408-
result = _get_type_hint(autodoc_mock_imports, name, obj)
410+
def get_all_type_hints(
411+
autodoc_mock_imports: list[str], obj: Any, name: str, localns: TypeAliasNamespace
412+
) -> dict[str, Any]:
413+
result = _get_type_hint(autodoc_mock_imports, name, obj, localns)
409414
if not result:
410415
result = backfill_type_hints(obj, name)
411416
try:
412417
obj.__annotations__ = result
413418
except (AttributeError, TypeError):
414419
pass
415420
else:
416-
result = _get_type_hint(autodoc_mock_imports, name, obj)
421+
result = _get_type_hint(autodoc_mock_imports, name, obj, localns)
417422
return result
418423

419424

@@ -474,10 +479,10 @@ def _resolve_type_guarded_imports(autodoc_mock_imports: list[str], obj: Any) ->
474479
_execute_guarded_code(autodoc_mock_imports, obj, module_code)
475480

476481

477-
def _get_type_hint(autodoc_mock_imports: list[str], name: str, obj: Any) -> dict[str, Any]:
482+
def _get_type_hint(autodoc_mock_imports: list[str], name: str, obj: Any, localns: TypeAliasNamespace) -> dict[str, Any]:
478483
_resolve_type_guarded_imports(autodoc_mock_imports, obj)
479484
try:
480-
result = get_type_hints(obj)
485+
result = get_type_hints(obj, None, localns)
481486
except (AttributeError, TypeError, RecursionError) as exc:
482487
# TypeError - slot wrapper, PEP-563 when part of new syntax not supported
483488
# RecursionError - some recursive type definitions https://github.com/python/typing/issues/574
@@ -645,7 +650,9 @@ def process_docstring( # noqa: PLR0913, PLR0917
645650
signature = sphinx_signature(obj, type_aliases=app.config["autodoc_type_aliases"])
646651
except (ValueError, TypeError):
647652
signature = None
648-
type_hints = get_all_type_hints(app.config.autodoc_mock_imports, obj, name)
653+
654+
localns = TypeAliasNamespace(app.config["autodoc_type_aliases"])
655+
type_hints = get_all_type_hints(app.config.autodoc_mock_imports, obj, name, localns)
649656
app.config._annotation_globals = getattr(obj, "__globals__", {}) # type: ignore[attr-defined] # noqa: SLF001
650657
try:
651658
_inject_types_to_docstring(type_hints, signature, original_obj, app, what, name, lines)
@@ -715,10 +722,8 @@ def _inject_signature( # noqa: C901
715722
app: Sphinx,
716723
lines: list[str],
717724
) -> None:
718-
type_aliases = app.config["autodoc_type_aliases"]
719-
720-
for arg_name, arg_type in signature.parameters.items():
721-
annotation = arg_type.annotation if arg_type.annotation in type_aliases else type_hints.get(arg_name)
725+
for arg_name in signature.parameters:
726+
annotation = type_hints.get(arg_name)
722727

723728
default = signature.parameters[arg_name].default
724729

tests/test_integration_autodoc_type_aliases.py

+67-11
Original file line numberDiff line numberDiff line change
@@ -37,41 +37,97 @@ def dec(val: T) -> T:
3737
ArrayLike = Literal["test"]
3838

3939

40+
class _SchemaMeta(type): # noqa: PLW1641
41+
def __eq__(cls, other: object) -> bool:
42+
return True
43+
44+
45+
class Schema(metaclass=_SchemaMeta):
46+
pass
47+
48+
49+
@expected(
50+
"""
51+
mod.f(s)
52+
53+
Do something.
54+
55+
Parameters:
56+
**s** ("Schema") -- Some schema.
57+
58+
Return type:
59+
"Schema"
60+
"""
61+
)
62+
def f(s: Schema) -> Schema:
63+
"""
64+
Do something.
65+
66+
Args:
67+
s: Some schema.
68+
"""
69+
return s
70+
71+
72+
class AliasedClass: ...
73+
74+
75+
@expected(
76+
"""
77+
mod.g(s)
78+
79+
Do something.
80+
81+
Parameters:
82+
**s** ("Class Alias") -- Some schema.
83+
84+
Return type:
85+
"Class Alias"
86+
"""
87+
)
88+
def g(s: AliasedClass) -> AliasedClass:
89+
"""
90+
Do something.
91+
92+
Args:
93+
s: Some schema.
94+
"""
95+
return s
96+
97+
4098
@expected(
4199
"""\
42-
mod.function(x)
100+
mod.function(x, y)
43101
44102
Function docstring.
45103
46104
Parameters:
47-
**x** (ArrayLike) -- foo
105+
* **x** (Array) -- foo
106+
107+
* **y** ("Schema") -- boo
48108
49109
Returns:
50110
something
51111
52112
Return type:
53113
bytes
114+
54115
""",
55116
)
56-
def function(x: ArrayLike) -> str: # noqa: ARG001
117+
def function(x: ArrayLike, y: Schema) -> str: # noqa: ARG001
57118
"""
58119
Function docstring.
59120
60121
:param x: foo
122+
:param y: boo
61123
:return: something
62124
:rtype: bytes
63125
"""
64126

65127

66128
# Config settings for each test run.
67129
# Config Name: Sphinx Options as Dict.
68-
configs = {
69-
"default_conf": {
70-
"autodoc_type_aliases": {
71-
"ArrayLike": "ArrayLike",
72-
}
73-
}
74-
}
130+
configs = {"default_conf": {"autodoc_type_aliases": {"ArrayLike": "Array", "AliasedClass": '"Class Alias"'}}}
75131

76132

77133
@pytest.mark.parametrize("val", [x for x in globals().values() if hasattr(x, "EXPECTED")])
@@ -94,7 +150,7 @@ def test_integration(
94150
if regexp:
95151
msg = f"Regex pattern did not match.\n Regex: {regexp!r}\n Input: {value!r}"
96152
assert re.search(regexp, value), msg
97-
else:
153+
elif not re.search("WARNING: Inline strong start-string without end-string.", value):
98154
assert not value
99155

100156
result = (Path(app.srcdir) / "_build/text/index.txt").read_text()

0 commit comments

Comments
 (0)