Skip to content

Commit

Permalink
[3.11] pythongh-97797: Improve documentation for typing.Annotated (py…
Browse files Browse the repository at this point in the history
…thonGH-105365).

(cherry picked from commit e26d296)

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
  • Loading branch information
AlexWaygood authored and JelleZijlstra committed Jun 7, 2023
1 parent ddbd481 commit d7dd378
Showing 1 changed file with 57 additions and 19 deletions.
76 changes: 57 additions & 19 deletions Doc/library/typing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
:mod:`typing` --- Support for type hints
========================================

.. testsetup:: *

import typing
from dataclasses import dataclass
from typing import *

.. module:: typing
:synopsis: Support for type hints (see :pep:`484`).

Expand Down Expand Up @@ -1093,7 +1099,8 @@ These can be used as types in annotations using ``[]``, each having a unique syn
(possibly multiple pieces of it, as ``Annotated`` is variadic).
Specifically, a type ``T`` can be annotated with metadata ``x`` via the
typehint ``Annotated[T, x]``. This metadata can be used for either static
analysis or at runtime. If a library (or tool) encounters a typehint
analysis or at runtime: at runtime, it is stored in a :attr:`__metadata__`
attribute. If a library (or tool) encounters a typehint
``Annotated[T, x]`` and has no special logic for metadata ``x``, it
should ignore it and simply treat the type as ``T``. Unlike the
``no_type_check`` functionality that currently exists in the ``typing``
Expand All @@ -1120,10 +1127,17 @@ These can be used as types in annotations using ``[]``, each having a unique syn
the same (or different) type(s) on any node, the tools or libraries
consuming those annotations are in charge of dealing with potential
duplicates. For example, if you are doing value range analysis you might
allow this::
allow this:

.. testcode::

T1 = Annotated[int, ValueRange(-10, 5)]
T2 = Annotated[T1, ValueRange(-20, 3)]
@dataclass
class ValueRange:
lo: int
hi: int

T1 = Annotated[int, ValueRange(-10, 5)]
T2 = Annotated[T1, ValueRange(-20, 3)]

Passing ``include_extras=True`` to :func:`get_type_hints` lets one
access the extra annotations at runtime.
Expand All @@ -1135,38 +1149,62 @@ These can be used as types in annotations using ``[]``, each having a unique syn
* Multiple type annotations are supported (``Annotated`` supports variadic
arguments)::

Annotated[int, ValueRange(3, 10), ctype("char")]
@dataclass
class ctype:
kind: str

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

* ``Annotated`` must be called with at least two arguments (
``Annotated[int]`` is not valid)

* The order of the annotations is preserved and matters for equality
checks::

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

* Nested ``Annotated`` types are flattened, with metadata ordered
starting with the innermost annotation::

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 annotations are not removed::

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:

.. testcode::

@dataclass
class MaxLen:
value: int

Vec = Annotated[list[tuple[T, T]], MaxLen(10)]

assert Vec[int] == Annotated[list[tuple[int, int]], MaxLen(10)]

.. attribute:: __metadata__

At runtime, the metadata associated with an ``Annotated`` type can be
retrieved via the ``__metadata__`` attribute.

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

T = TypeVar('T')
Vec = Annotated[list[tuple[T, T]], MaxLen(10)]
V = Vec[int]
.. doctest::

V == Annotated[list[tuple[int, int]], MaxLen(10)]
>>> from typing import Annotated
>>> X = Annotated[int, "very", "important", "metadata"]
>>> X
typing.Annotated[int, 'very', 'important', 'metadata']
>>> X.__metadata__
('very', 'important', 'metadata')

.. versionadded:: 3.9

Expand Down

0 comments on commit d7dd378

Please sign in to comment.