Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gh-124269: Simplify typing.Annotated docs #130770

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 34 additions & 53 deletions Doc/library/typing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1368,47 +1368,38 @@ These can be used as types in annotations. They all support subscription using
T1 = Annotated[int, ValueRange(-10, 5)]
T2 = Annotated[T1, ValueRange(-20, 3)]

Details of the syntax:
The first argument to ``Annotated`` must be a valid type. Multiple metadata
elements can be supplied as ``Annotated`` supports variadic arguments. The
order of the metadata elements is preserved and matters for equality checks::

* The first argument to ``Annotated`` must be a valid type

* Multiple metadata elements can be supplied (``Annotated`` supports variadic
arguments)::

@dataclass
class ctype:
kind: str

Annotated[int, ValueRange(3, 10), ctype("char")]

It is up to the tool consuming the annotations to decide whether the
client is allowed to add multiple metadata elements to one annotation and how to
merge those annotations.
@dataclass
class ctype:
kind: str

* ``Annotated`` must be subscripted with at least two arguments (
``Annotated[int]`` is not valid)
Annotated[int, ValueRange(3, 10), ctype("char")]

* The order of the metadata elements is preserved and matters for equality
checks::
assert Annotated[int, ValueRange(3, 10), ctype("char")] != Annotated[
int, ctype("char"), ValueRange(3, 10)
] # Order matters

assert Annotated[int, ValueRange(3, 10), ctype("char")] != Annotated[
int, ctype("char"), ValueRange(3, 10)
]
It is up to the tool consuming the annotations to decide whether the
client is allowed to add multiple metadata elements to one annotation and how to
merge those annotations.

* Nested ``Annotated`` types are flattened. The order of the metadata elements
starts with the innermost annotation::
Nested ``Annotated`` types are flattened. The order of the metadata elements
starts with the innermost annotation::

assert Annotated[Annotated[int, ValueRange(3, 10)], ctype("char")] == Annotated[
int, ValueRange(3, 10), ctype("char")
]
assert Annotated[Annotated[int, ValueRange(3, 10)], ctype("char")] == Annotated[
int, ValueRange(3, 10), ctype("char")
]

* Duplicated metadata elements are not removed::
Duplicated metadata elements are not removed::

assert Annotated[int, ValueRange(3, 10)] != Annotated[
int, ValueRange(3, 10), ValueRange(3, 10)
]
assert Annotated[int, ValueRange(3, 10)] != Annotated[
int, ValueRange(3, 10), ValueRange(3, 10)
]

* ``Annotated`` can be used with nested and generic aliases:
``Annotated`` can be used with nested and generic aliases:

.. testcode::

Expand All @@ -1422,19 +1413,15 @@ These can be used as types in annotations. They all support subscription using
# ``Annotated[list[tuple[int, int]], MaxLen(10)]``:
type V = Vec[int]

* ``Annotated`` cannot be used with an unpacked :class:`TypeVarTuple`::

type Variadic[*Ts] = Annotated[*Ts, Ann1] # NOT valid
``Annotated`` cannot be used with an unpacked :class:`TypeVarTuple`::

This would be equivalent to::
type Variadic[*Ts] = Annotated[*Ts, Ann1] = Annotated[T1, T2, T3, ..., Ann1] # NOT valid

Annotated[T1, T2, T3, ..., Ann1]
where ``T1``, ``T2``, ... are :class:`TypeVars <TypeVar>`. This is invalid as
only one type should be passed to Annotated.

where ``T1``, ``T2``, etc. are :class:`TypeVars <TypeVar>`. This would be
invalid: only one type should be passed to Annotated.

* By default, :func:`get_type_hints` strips the metadata from annotations.
Pass ``include_extras=True`` to have the metadata preserved:
By default, :func:`get_type_hints` strips the metadata from annotations.
Pass ``include_extras=True`` to have the metadata preserved:

.. doctest::

Expand All @@ -1446,29 +1433,23 @@ These can be used as types in annotations. They all support subscription using
>>> get_type_hints(func, include_extras=True)
{'x': typing.Annotated[int, 'metadata'], 'return': <class 'NoneType'>}

* At runtime, the metadata associated with an ``Annotated`` type can be
retrieved via the :attr:`!__metadata__` attribute:
At runtime, the metadata associated with an ``Annotated`` type can be
retrieved via the :attr:`!__metadata__` attribute. If you want to retrieve
the original type wrapped by ``Annotated``, use the :attr:`!__origin__` attribute:

.. doctest::

>>> from typing import Annotated
>>> from typing import Annotated, get_origin
>>> X = Annotated[int, "very", "important", "metadata"]
>>> X
typing.Annotated[int, 'very', 'important', 'metadata']
>>> X.__metadata__
('very', 'important', 'metadata')

* At runtime, if you want to retrieve the original
type wrapped by ``Annotated``, use the :attr:`!__origin__` attribute:

.. doctest::

>>> from typing import Annotated, get_origin
>>> Password = Annotated[str, "secret"]
>>> Password.__origin__
<class 'str'>

Note that using :func:`get_origin` will return ``Annotated`` itself:
Note that using :func:`get_origin` will return ``Annotated`` itself:

.. doctest::

Expand Down
Loading