diff --git a/sphinx/util/typing.py b/sphinx/util/typing.py index 4e1b184e0a..4450d4edb6 100644 --- a/sphinx/util/typing.py +++ b/sphinx/util/typing.py @@ -310,7 +310,10 @@ def stringify(annotation: Any) -> str: return INVALID_BUILTIN_CLASSES[annotation] elif (getattr(annotation, '__module__', None) == 'builtins' and hasattr(annotation, '__qualname__')): - return annotation.__qualname__ + if hasattr(annotation, '__args__'): # PEP 585 generic + return repr(annotation) + else: + return annotation.__qualname__ elif annotation is Ellipsis: return '...' diff --git a/tests/test_util_typing.py b/tests/test_util_typing.py index d0c511d25b..04125a73a8 100644 --- a/tests/test_util_typing.py +++ b/tests/test_util_typing.py @@ -175,6 +175,18 @@ def test_stringify_type_hints_containers(): assert stringify(Generator[None, None, None]) == "Generator[None, None, None]" +@pytest.mark.skipif(sys.version_info < (3, 9), reason='python 3.9+ is required.') +def test_stringify_type_hints_pep_585(): + assert stringify(list[int]) == "list[int]" + assert stringify(list[str]) == "list[str]" + assert stringify(dict[str, float]) == "dict[str, float]" + assert stringify(tuple[str, str, str]) == "tuple[str, str, str]" + assert stringify(tuple[str, ...]) == "tuple[str, ...]" + assert stringify(tuple[()]) == "tuple[()]" + assert stringify(list[dict[str, tuple]]) == "list[dict[str, tuple]]" + assert stringify(type[int]) == "type[int]" + + @pytest.mark.skipif(sys.version_info < (3, 9), reason='python 3.9+ is required.') def test_stringify_Annotated(): from typing import Annotated # type: ignore