Skip to content

Commit

Permalink
Add support for recursive type hints (#248)
Browse files Browse the repository at this point in the history
Co-authored-by: Mehdi Drissi <[email protected]>
  • Loading branch information
hmc-cs-mdrissi and Mehdi Drissi authored Jul 31, 2022
1 parent 1ef3776 commit 5bb2358
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 15 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## 1.19.1

- Fix bug for recursive type alias.

## 1.19.0

- Support for CPython 3.11, no longer adds `Optional` when the argument is default per
Expand Down
15 changes: 1 addition & 14 deletions src/sphinx_autodoc_typehints/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import sys
import textwrap
from ast import FunctionDef, Module, stmt
from typing import _eval_type # type: ignore # no import defined in stubs
from typing import Any, AnyStr, Callable, ForwardRef, NewType, TypeVar, get_type_hints

from sphinx.application import Sphinx
Expand Down Expand Up @@ -120,8 +119,7 @@ def format_annotation(annotation: Any, config: Config) -> str: # noqa: C901 # t

# Special cases
if isinstance(annotation, ForwardRef):
value = _resolve_forward_ref(annotation, config)
return format_annotation(value, config)
return annotation.__forward_arg__
if annotation is None or annotation is type(None): # noqa: E721
return ":py:obj:`None`"
if annotation is Ellipsis:
Expand Down Expand Up @@ -195,17 +193,6 @@ def format_annotation(annotation: Any, config: Config) -> str: # noqa: C901 # t
return result


def _resolve_forward_ref(annotation: ForwardRef, config: Config) -> Any:
raw, base_globals = annotation.__forward_arg__, config._annotation_globals
params = {"is_class": True} if (3, 10) > sys.version_info >= (3, 9, 8) or sys.version_info >= (3, 10, 1) else {}
value = ForwardRef(raw, is_argument=False, **params)
try:
result = _eval_type(value, base_globals, None)
except NameError:
result = raw # fallback to the value itself as string
return result


# reference: https://github.com/pytorch/pytorch/pull/46548/files
def normalize_source_lines(source_lines: str) -> str:
"""
Expand Down
17 changes: 16 additions & 1 deletion tests/test_sphinx_autodoc_typehints.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
Callable,
Dict,
Generic,
List,
Mapping,
Match,
NewType,
Expand Down Expand Up @@ -55,6 +56,12 @@
S = TypeVar("S", bound="miss") # type: ignore # miss not defined on purpose # noqa: F821
W = NewType("W", str)

# Mypy does not support recursive type aliases, but
# other type checkers do.
RecList = Union[int, List["RecList"]] # type: ignore
MutualRecA = Union[bool, List["MutualRecB"]] # type: ignore
MutualRecB = Union[str, List["MutualRecA"]] # type: ignore


class A:
def get_type(self) -> type:
Expand Down Expand Up @@ -228,7 +235,7 @@ def test_parse_annotation(annotation: Any, module: str, class_name: str, args: t
(V, ":py:class:`~typing.TypeVar`\\(``V``, contravariant=True)"),
(X, ":py:class:`~typing.TypeVar`\\(``X``, :py:class:`str`, :py:class:`int`)"),
(Y, ":py:class:`~typing.TypeVar`\\(``Y``, bound= :py:class:`str`)"),
(Z, ":py:class:`~typing.TypeVar`\\(``Z``, bound= :py:class:`~test_sphinx_autodoc_typehints.A`)"),
(Z, ":py:class:`~typing.TypeVar`\\(``Z``, bound= A)"),
(S, ":py:class:`~typing.TypeVar`\\(``S``, bound= miss)"),
# ## These test for correct internal tuple rendering, even if not all are valid Tuple types
# Zero-length tuple remains
Expand Down Expand Up @@ -279,6 +286,14 @@ def test_parse_annotation(annotation: Any, module: str, class_name: str, args: t
"...], :py:class:`~numpy.float64`]"
),
),
(
RecList,
(":py:data:`~typing.Union`\\[:py:class:`int`, :py:class:`~typing.List`\\[RecList]]"),
),
(
MutualRecA,
(":py:data:`~typing.Union`\\[:py:class:`bool`, :py:class:`~typing.List`\\[MutualRecB]]"),
),
],
)
def test_format_annotation(inv: Inventory, annotation: Any, expected_result: str) -> None:
Expand Down

0 comments on commit 5bb2358

Please sign in to comment.