Skip to content

Commit 09d05a0

Browse files
AA-Turnerpicnixz
andcommitted
Don't render types with Optional[...]
Co-authored-by: Bénédikt Tran <[email protected]>
1 parent 5ed1921 commit 09d05a0

File tree

3 files changed

+45
-38
lines changed

3 files changed

+45
-38
lines changed

sphinx/util/typing.py

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -186,11 +186,7 @@ def restify(cls: type | None, mode: str = 'fully-qualified-except-typing') -> st
186186
else:
187187
return ':py:class:`%s`' % cls.__name__
188188
elif UnionType and isinstance(cls, UnionType):
189-
if len(cls.__args__) > 1 and None in cls.__args__:
190-
args = ' | '.join(restify(a, mode) for a in cls.__args__ if a)
191-
return 'Optional[%s]' % args
192-
else:
193-
return ' | '.join(restify(a, mode) for a in cls.__args__)
189+
return ' | '.join(restify(a, mode) for a in cls.__args__)
194190
elif cls.__module__ in ('__builtin__', 'builtins'):
195191
if hasattr(cls, '__args__'):
196192
if not cls.__args__: # Empty tuple, list, ...
@@ -203,19 +199,7 @@ def restify(cls: type | None, mode: str = 'fully-qualified-except-typing') -> st
203199
elif (inspect.isgenericalias(cls)
204200
and cls.__module__ == 'typing'
205201
and cls.__origin__ is Union): # type: ignore[attr-defined]
206-
if (len(cls.__args__) > 1 # type: ignore[attr-defined]
207-
and cls.__args__[-1] is NoneType): # type: ignore[attr-defined]
208-
if len(cls.__args__) > 2: # type: ignore[attr-defined]
209-
args = ', '.join(restify(a, mode)
210-
for a in cls.__args__[:-1]) # type: ignore[attr-defined]
211-
return ':py:obj:`~typing.Optional`\\ [:obj:`~typing.Union`\\ [%s]]' % args
212-
else:
213-
return ':py:obj:`~typing.Optional`\\ [%s]' % restify(
214-
cls.__args__[0], mode) # type: ignore[attr-defined]
215-
else:
216-
args = ', '.join(restify(a, mode)
217-
for a in cls.__args__) # type: ignore[attr-defined]
218-
return ':py:obj:`~typing.Union`\\ [%s]' % args
202+
return ' | '.join(restify(a, mode) for a in cls.__args__) # type: ignore[attr-defined]
219203
elif inspect.isgenericalias(cls):
220204
if isinstance(cls.__origin__, typing._SpecialForm): # type: ignore[attr-defined]
221205
text = restify(cls.__origin__, mode) # type: ignore[attr-defined,arg-type]

tests/test_extensions/test_ext_autodoc_autoclass.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -276,8 +276,7 @@ def test_show_inheritance_for_subclass_of_generic_type(app):
276276
'.. py:class:: Quux(iterable=(), /)',
277277
' :module: target.classes',
278278
'',
279-
' Bases: :py:class:`~typing.List`\\ '
280-
'[:py:obj:`~typing.Union`\\ [:py:class:`int`, :py:class:`float`]]',
279+
' Bases: :py:class:`~typing.List`\\ [:py:class:`int` | :py:class:`float`]',
281280
'',
282281
' A subclass of List[Union[int, float]]',
283282
'',

tests/test_util/test_util_typing.py

Lines changed: 42 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -190,24 +190,44 @@ def test_restify_type_hints_Callable():
190190

191191

192192
def test_restify_type_hints_Union():
193-
assert restify(Optional[int]) == ":py:obj:`~typing.Optional`\\ [:py:class:`int`]"
194-
assert restify(Union[str, None]) == ":py:obj:`~typing.Optional`\\ [:py:class:`str`]"
195-
assert restify(Union[int, str]) == (":py:obj:`~typing.Union`\\ "
196-
"[:py:class:`int`, :py:class:`str`]")
197-
assert restify(Union[int, Integral]) == (":py:obj:`~typing.Union`\\ "
198-
"[:py:class:`int`, :py:class:`numbers.Integral`]")
199-
assert restify(Union[int, Integral], "smart") == (":py:obj:`~typing.Union`\\ "
200-
"[:py:class:`int`,"
201-
" :py:class:`~numbers.Integral`]")
193+
assert restify(Union[int]) == ":py:class:`int`"
194+
assert restify(Union[int, str]) == ":py:class:`int` | :py:class:`str`"
195+
assert restify(Optional[int]) == ":py:class:`int` | :py:obj:`None`"
196+
197+
assert restify(Union[str, None]) == ":py:class:`str` | :py:obj:`None`"
198+
assert restify(Union[None, str]) == ":py:obj:`None` | :py:class:`str`"
199+
assert restify(Optional[str]) == ":py:class:`str` | :py:obj:`None`"
200+
201+
assert restify(Union[int, str, None]) == (
202+
":py:class:`int` | :py:class:`str` | :py:obj:`None`"
203+
)
204+
assert restify(Optional[Union[int, str]]) in {
205+
":py:class:`str` | :py:class:`int` | :py:obj:`None`",
206+
":py:class:`int` | :py:class:`str` | :py:obj:`None`",
207+
}
208+
209+
assert restify(Union[int, Integral]) == (
210+
":py:class:`int` | :py:class:`numbers.Integral`"
211+
)
212+
assert restify(Union[int, Integral], "smart") == (
213+
":py:class:`int` | :py:class:`~numbers.Integral`"
214+
)
202215

203216
assert (restify(Union[MyClass1, MyClass2]) ==
204-
(":py:obj:`~typing.Union`\\ "
205-
"[:py:class:`tests.test_util.test_util_typing.MyClass1`, "
206-
":py:class:`tests.test_util.test_util_typing.<MyClass2>`]"))
217+
(":py:class:`tests.test_util.test_util_typing.MyClass1`"
218+
" | :py:class:`tests.test_util.test_util_typing.<MyClass2>`"))
207219
assert (restify(Union[MyClass1, MyClass2], "smart") ==
208-
(":py:obj:`~typing.Union`\\ "
209-
"[:py:class:`~tests.test_util.test_util_typing.MyClass1`,"
210-
" :py:class:`~tests.test_util.test_util_typing.<MyClass2>`]"))
220+
(":py:class:`~tests.test_util.test_util_typing.MyClass1`"
221+
" | :py:class:`~tests.test_util.test_util_typing.<MyClass2>`"))
222+
223+
assert (restify(Optional[Union[MyClass1, MyClass2]]) ==
224+
(":py:class:`tests.test_util.test_util_typing.MyClass1`"
225+
" | :py:class:`tests.test_util.test_util_typing.<MyClass2>`"
226+
" | :py:obj:`None`"))
227+
assert (restify(Optional[Union[MyClass1, MyClass2]], "smart") ==
228+
(":py:class:`~tests.test_util.test_util_typing.MyClass1`"
229+
" | :py:class:`~tests.test_util.test_util_typing.<MyClass2>`"
230+
" | :py:obj:`None`"))
211231

212232

213233
def test_restify_type_hints_typevars():
@@ -300,6 +320,7 @@ def test_restify_pep_585():
300320
@pytest.mark.skipif(sys.version_info[:2] <= (3, 9), reason='python 3.10+ is required.')
301321
def test_restify_type_union_operator():
302322
assert restify(int | None) == ":py:class:`int` | :py:obj:`None`" # type: ignore[attr-defined]
323+
assert restify(None | int) == ":py:obj:`None` | :py:class:`int`" # type: ignore[attr-defined]
303324
assert restify(int | str) == ":py:class:`int` | :py:class:`str`" # type: ignore[attr-defined]
304325
assert restify(int | str | None) == (":py:class:`int` | :py:class:`str` | " # type: ignore[attr-defined]
305326
":py:obj:`None`")
@@ -486,9 +507,12 @@ def test_stringify_type_hints_Union():
486507
assert stringify_annotation(Optional[int], "fully-qualified") == "int | None"
487508
assert stringify_annotation(Optional[int], "smart") == "int | None"
488509

489-
assert stringify_annotation(Union[str, None], 'fully-qualified-except-typing') == "str | None"
490-
assert stringify_annotation(Union[str, None], "fully-qualified") == "str | None"
491-
assert stringify_annotation(Union[str, None], "smart") == "str | None"
510+
assert stringify_annotation(Union[int, None], 'fully-qualified-except-typing') == "int | None"
511+
assert stringify_annotation(Union[None, int], 'fully-qualified-except-typing') == "None | int"
512+
assert stringify_annotation(Union[int, None], "fully-qualified") == "int | None"
513+
assert stringify_annotation(Union[None, int], "fully-qualified") == "None | int"
514+
assert stringify_annotation(Union[int, None], "smart") == "int | None"
515+
assert stringify_annotation(Union[None, int], "smart") == "None | int"
492516

493517
assert stringify_annotation(Union[int, str], 'fully-qualified-except-typing') == "int | str"
494518
assert stringify_annotation(Union[int, str], "fully-qualified") == "int | str"

0 commit comments

Comments
 (0)