From a30f2b99c354a6ef0c8a2820c130e68d87912624 Mon Sep 17 00:00:00 2001 From: James <50501825+Gobot1234@users.noreply.github.com> Date: Sun, 1 Aug 2021 18:53:00 +0100 Subject: [PATCH 1/4] Recursively resolve PEP 585 builtins --- sphinx/util/typing.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sphinx/util/typing.py b/sphinx/util/typing.py index 4450d4edb69..bd2a2ad3815 100644 --- a/sphinx/util/typing.py +++ b/sphinx/util/typing.py @@ -121,7 +121,10 @@ 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) From d480447cc6a6de3f836e6f546344526a5a7032ff Mon Sep 17 00:00:00 2001 From: James <50501825+Gobot1234@users.noreply.github.com> Date: Sun, 1 Aug 2021 19:01:55 +0100 Subject: [PATCH 2/4] Match formatting of other recursive types --- sphinx/util/typing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sphinx/util/typing.py b/sphinx/util/typing.py index bd2a2ad3815..94a84d96fbf 100644 --- a/sphinx/util/typing.py +++ b/sphinx/util/typing.py @@ -122,7 +122,7 @@ def restify(cls: Optional[Type]) -> str: return ' | '.join(restify(a) for a in cls.__args__) elif cls.__module__ in ('__builtin__', 'builtins'): if hasattr(cls, '__args__'): - return ':class:`%s`\\[%s]' % (cls.__name__, ', '.join(restify(arg) for arg in cls.__args__)) + return ':class:`%s`\\ [%s]' % (cls.__name__, ', '.join(restify(arg) for arg in cls.__args__)) else: return ':class:`%s`' % cls.__name__ else: From 15fb9c64bf8e9b4c9302ac90da636a4cdb7bac8e Mon Sep 17 00:00:00 2001 From: James <50501825+Gobot1234@users.noreply.github.com> Date: Sun, 1 Aug 2021 19:08:38 +0100 Subject: [PATCH 3/4] Appease linter --- sphinx/util/typing.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sphinx/util/typing.py b/sphinx/util/typing.py index 94a84d96fbf..deba6b53d56 100644 --- a/sphinx/util/typing.py +++ b/sphinx/util/typing.py @@ -122,7 +122,10 @@ def restify(cls: Optional[Type]) -> str: return ' | '.join(restify(a) for a in cls.__args__) elif cls.__module__ in ('__builtin__', 'builtins'): if hasattr(cls, '__args__'): - return ':class:`%s`\\ [%s]' % (cls.__name__, ', '.join(restify(arg) for arg in cls.__args__)) + return ':class:`%s`\\ [%s]' % ( + cls.__name__, + ', '.join(restify(arg) for arg in cls.__args__), + ) else: return ':class:`%s`' % cls.__name__ else: From 423b10a84843a629b96b6893a08819a1e07927af Mon Sep 17 00:00:00 2001 From: James <50501825+Gobot1234@users.noreply.github.com> Date: Mon, 2 Aug 2021 00:20:08 +0100 Subject: [PATCH 4/4] Add some tests --- tests/test_util_typing.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tests/test_util_typing.py b/tests/test_util_typing.py index afa5384f7af..e9496440132 100644 --- a/tests/test_util_typing.py +++ b/tests/test_util_typing.py @@ -140,13 +140,21 @@ def test_restify_type_Literal(): assert restify(Literal[1, "2", "\r"]) == ":obj:`~typing.Literal`\\ [1, '2', '\\r']" -@pytest.mark.skipif(sys.version_info < (3, 10), reason='python 3.10+ is required.') -def test_restify_type_union_operator(): +@pytest.mark.skipif(sys.version_info < (3, 9), reason='python 3.9+ is required.') +def test_restify_pep_585(): assert restify(int | None) == "Optional[:class:`int`]" # type: ignore assert restify(int | str) == ":class:`int` | :class:`str`" # type: ignore assert restify(int | str | None) == "Optional[:class:`int` | :class:`str`]" # type: ignore +@pytest.mark.skipif(sys.version_info < (3, 10), reason='python 3.10+ is required.') +def test_restify_type_union_operator(): + 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 + + def test_restify_broken_type_hints(): assert restify(BrokenType) == ':class:`tests.test_util_typing.BrokenType`'