mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Collapse unions of `Literal
types in
stringify_annotation
` (#12325)
This commit is contained in:
parent
7953798074
commit
938d3732f8
@ -18,6 +18,9 @@ Features added
|
|||||||
Patch by James Addison and Adam Turner
|
Patch by James Addison and Adam Turner
|
||||||
|
|
||||||
.. _officially recommended: https://jinja.palletsprojects.com/en/latest/templates/#template-file-extension
|
.. _officially recommended: https://jinja.palletsprojects.com/en/latest/templates/#template-file-extension
|
||||||
|
* Flatten ``Union[Literal[T], Literal[U], ...]`` to ``Literal[T, U, ...]``
|
||||||
|
when turning annotations into strings.
|
||||||
|
Patch by Adam Turner.
|
||||||
|
|
||||||
Bugs fixed
|
Bugs fixed
|
||||||
----------
|
----------
|
||||||
|
@ -439,6 +439,15 @@ def stringify_annotation(
|
|||||||
# They must be a list or a tuple, otherwise they are considered 'broken'.
|
# They must be a list or a tuple, otherwise they are considered 'broken'.
|
||||||
annotation_args = getattr(annotation, '__args__', ())
|
annotation_args = getattr(annotation, '__args__', ())
|
||||||
if annotation_args and isinstance(annotation_args, (list, tuple)):
|
if annotation_args and isinstance(annotation_args, (list, tuple)):
|
||||||
|
if (
|
||||||
|
qualname in {'Union', 'types.UnionType'}
|
||||||
|
and all(getattr(a, '__origin__', ...) is typing.Literal for a in annotation_args)
|
||||||
|
):
|
||||||
|
# special case to flatten a Union of Literals into a literal
|
||||||
|
flattened_args = typing.Literal[annotation_args].__args__ # type: ignore[attr-defined]
|
||||||
|
args = ', '.join(_format_literal_arg_stringify(a, mode=mode)
|
||||||
|
for a in flattened_args)
|
||||||
|
return f'{module_prefix}Literal[{args}]'
|
||||||
if qualname in {'Optional', 'Union', 'types.UnionType'}:
|
if qualname in {'Optional', 'Union', 'types.UnionType'}:
|
||||||
return ' | '.join(stringify_annotation(a, mode) for a in annotation_args)
|
return ' | '.join(stringify_annotation(a, mode) for a in annotation_args)
|
||||||
elif qualname == 'Callable':
|
elif qualname == 'Callable':
|
||||||
|
@ -359,6 +359,10 @@ def test_signature_annotations():
|
|||||||
sig = inspect.signature(mod.f25)
|
sig = inspect.signature(mod.f25)
|
||||||
assert stringify_signature(sig) == '(a, b, /)'
|
assert stringify_signature(sig) == '(a, b, /)'
|
||||||
|
|
||||||
|
# collapse Literal types
|
||||||
|
sig = inspect.signature(mod.f26)
|
||||||
|
assert stringify_signature(sig) == "(x: typing.Literal[1, 2, 3] = 1, y: typing.Literal['a', 'b'] = 'a') -> None"
|
||||||
|
|
||||||
|
|
||||||
def test_signature_from_str_basic():
|
def test_signature_from_str_basic():
|
||||||
signature = '(a, b, *args, c=0, d="blah", **kwargs)'
|
signature = '(a, b, *args, c=0, d="blah", **kwargs)'
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
from inspect import Signature
|
from inspect import Signature
|
||||||
from numbers import Integral
|
from numbers import Integral
|
||||||
from typing import Any, Callable, Dict, List, Optional, Tuple, TypeVar, Union
|
from typing import Any, Callable, Dict, List, Literal, Optional, Tuple, TypeVar, Union
|
||||||
|
|
||||||
|
|
||||||
def f0(x: int, y: Integral) -> None:
|
def f0(x: int, y: Integral) -> None:
|
||||||
@ -121,6 +121,10 @@ def f25(a, b, /):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def f26(x: Literal[1, 2, 3] = 1, y: Union[Literal["a"], Literal["b"]] = "a") -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class Node:
|
class Node:
|
||||||
def __init__(self, parent: Optional['Node']) -> None:
|
def __init__(self, parent: Optional['Node']) -> None:
|
||||||
pass
|
pass
|
||||||
|
Loading…
Reference in New Issue
Block a user