diff --git a/sphinx/util/typing.py b/sphinx/util/typing.py index fd5735c579d..78feb64929e 100644 --- a/sphinx/util/typing.py +++ b/sphinx/util/typing.py @@ -124,7 +124,13 @@ def restify(cls: Optional[Type]) -> str: else: return ' | '.join(restify(a) for a in cls.__args__) elif cls.__module__ in ('__builtin__', 'builtins'): - return ':class:`%s`' % cls.__name__ + if hasattr(cls, '__args__'): + return ':class:`%s`\\ [%s]' % ( + cls.__name__, + ', '.join(restify(arg) for arg in cls.__args__), + ) + else: + return ':class:`%s`' % cls.__name__ else: if sys.version_info >= (3, 7): # py37+ return _restify_py37(cls) diff --git a/tests/test_util_typing.py b/tests/test_util_typing.py index 04125a73a83..9cb1d61ef5f 100644 --- a/tests/test_util_typing.py +++ b/tests/test_util_typing.py @@ -140,6 +140,14 @@ def test_restify_type_Literal(): assert restify(Literal[1, "2", "\r"]) == ":obj:`~typing.Literal`\\ [1, '2', '\\r']" +@pytest.mark.skipif(sys.version_info < (3, 9), reason='python 3.9+ is required.') +def test_restify_pep_585(): + assert restify(list[str]) == ":class:`list`\\ [:class:`str`]" # type: ignore + assert restify(dict[str, str]) == ":class:`dict`\\ [:class:`str`, :class:`str`]" # type: ignore + assert restify(dict[str, tuple[int, ...]]) == \ + ":class:`dict`\\ [:class:`str`, :class:`tuple`\\ [:class:`int`, ...]]" # type: ignore + + @pytest.mark.skipif(sys.version_info < (3, 10), reason='python 3.10+ is required.') def test_restify_type_union_operator(): assert restify(int | None) == ":class:`int` | :obj:`None`" # type: ignore