Skip to content

Commit

Permalink
[3.12] Improve code examples in typing.rst (GH-105346) (#105422)
Browse files Browse the repository at this point in the history
Improve code examples in `typing.rst` (GH-105346)
(cherry picked from commit 81c8132)

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
  • Loading branch information
miss-islington and AlexWaygood authored Jun 7, 2023
1 parent a36fb69 commit 2cfe778
Showing 1 changed file with 75 additions and 30 deletions.
105 changes: 75 additions & 30 deletions Doc/library/typing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
:mod:`typing` --- Support for type hints
========================================

.. testsetup:: *

import typing
from typing import *

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

Expand Down Expand Up @@ -261,19 +266,22 @@ Callable
Frameworks expecting callback functions of specific signatures might be
type hinted using ``Callable[[Arg1Type, Arg2Type], ReturnType]``.

For example::
For example:

.. testcode::

from collections.abc import Callable

def feeder(get_next_item: Callable[[], str]) -> None:
# Body
... # Body

def async_query(on_success: Callable[[int], None],
on_error: Callable[[int, Exception], None]) -> None:
# Body
... # Body

async def on_update(value: str) -> None:
# Body
... # Body

callback: Callable[[str], Awaitable[None]] = on_update

It is possible to declare the return type of a callable without specifying
Expand Down Expand Up @@ -431,11 +439,14 @@ In this case ``MyDict`` has a single parameter, ``T``.

Using a generic class without specifying type parameters assumes
:data:`Any` for each position. In the following example, ``MyIterable`` is
not generic but implicitly inherits from ``Iterable[Any]``::
not generic but implicitly inherits from ``Iterable[Any]``:

.. testcode::

from collections.abc import Iterable

class MyIterable(Iterable): # Same as Iterable[Any]
...

User-defined generic type aliases are also supported. Examples::

Expand Down Expand Up @@ -701,9 +712,11 @@ These can be used as types in annotations and do not support ``[]``.
A string created by composing ``LiteralString``-typed objects
is also acceptable as a ``LiteralString``.

Example::
Example:

.. testcode::

def run_query(sql: LiteralString) -> ...
def run_query(sql: LiteralString) -> None:
...

def caller(arbitrary_string: str, literal_string: LiteralString) -> None:
Expand Down Expand Up @@ -1596,16 +1609,19 @@ without the dedicated syntax, as documented below.
def __abs__(self) -> "Array[*Shape]": ...
def get_shape(self) -> tuple[*Shape]: ...

Type variable tuples can be happily combined with normal type variables::
Type variable tuples can be happily combined with normal type variables:

DType = TypeVar('DType')
.. testcode::

class Array[DType, *Shape]: # This is fine
pass
class Array2[*Shape, DType]: # This would also be fine
pass
class Height: ...
class Width: ...

float_array_1d: Array[float, Height] = Array() # Totally fine
int_array_2d: Array[int, Height, Width] = Array() # Yup, fine too

Expand Down Expand Up @@ -1759,7 +1775,9 @@ without the dedicated syntax, as documented below.

The type of type aliases created through the :keyword:`type` statement.

Example::
Example:

.. doctest::

>>> type Alias = int
>>> type(Alias)
Expand All @@ -1769,7 +1787,9 @@ without the dedicated syntax, as documented below.

.. attribute:: __name__

The name of the type alias::
The name of the type alias:

.. doctest::

>>> type Alias = int
>>> Alias.__name__
Expand Down Expand Up @@ -2158,7 +2178,11 @@ These are not used in annotations. They are building blocks for declaring types.
group: list[T]

To create a generic ``TypedDict`` that is compatible with Python 3.11
or lower, inherit from :class:`Generic` explicitly::
or lower, inherit from :class:`Generic` explicitly:

.. testcode::

T = TypeVar("T")

class Group(TypedDict, Generic[T]):
key: T
Expand All @@ -2171,7 +2195,9 @@ These are not used in annotations. They are building blocks for declaring types.
.. attribute:: __total__

``Point2D.__total__`` gives the value of the ``total`` argument.
Example::
Example:

.. doctest::

>>> from typing import TypedDict
>>> class Point2D(TypedDict): pass
Expand Down Expand Up @@ -2201,7 +2227,9 @@ These are not used in annotations. They are building blocks for declaring types.
non-required keys in the same ``TypedDict`` . This is done by declaring a
``TypedDict`` with one value for the ``total`` argument and then
inheriting from it in another ``TypedDict`` with a different value for
``total``::
``total``:

.. doctest::

>>> class Point2D(TypedDict, total=False):
... x: int
Expand Down Expand Up @@ -2860,12 +2888,12 @@ Functions and decorators
decorated object performs runtime "magic" that
transforms a class, giving it :func:`dataclasses.dataclass`-like behaviors.

Example usage with a decorator function::
Example usage with a decorator function:

T = TypeVar("T")
.. testcode::

@dataclass_transform()
def create_model(cls: type[T]) -> type[T]:
def create_model[T](cls: type[T]) -> type[T]:
...
return cls

Expand Down Expand Up @@ -2969,7 +2997,9 @@ Functions and decorators
runtime but should be ignored by a type checker. At runtime, calling
a ``@overload``-decorated function directly will raise
:exc:`NotImplementedError`. An example of overload that gives a more
precise type than can be expressed using a union or a type variable::
precise type than can be expressed using a union or a type variable:

.. testcode::

@overload
def process(response: None) -> None:
Expand All @@ -2981,7 +3011,7 @@ Functions and decorators
def process(response: bytes) -> str:
...
def process(response):
<actual implementation>
... # actual implementation goes here

See :pep:`484` for more details and comparison with other typing semantics.

Expand Down Expand Up @@ -3073,10 +3103,13 @@ Functions and decorators
This helps prevent bugs that may occur when a base class is changed without
an equivalent change to a child class.

For example::
For example:

.. testcode::

class Base:
def log_status(self)
def log_status(self) -> None:
...

class Sub(Base):
@override
Expand Down Expand Up @@ -3135,14 +3168,16 @@ Introspection helpers

The function recursively replaces all ``Annotated[T, ...]`` with ``T``,
unless ``include_extras`` is set to ``True`` (see :class:`Annotated` for
more information). For example::
more information). For example:

.. testcode::

class Student(NamedTuple):
name: Annotated[str, 'some marker']

get_type_hints(Student) == {'name': str}
get_type_hints(Student, include_extras=False) == {'name': str}
get_type_hints(Student, include_extras=True) == {
assert get_type_hints(Student) == {'name': str}
assert get_type_hints(Student, include_extras=False) == {'name': str}
assert get_type_hints(Student, include_extras=True) == {
'name': Annotated[str, 'some marker']
}

Expand All @@ -3169,7 +3204,9 @@ Introspection helpers
If ``X`` is an instance of :class:`ParamSpecArgs` or :class:`ParamSpecKwargs`,
return the underlying :class:`ParamSpec`.
Return ``None`` for unsupported objects.
Examples::
Examples:

.. testcode::

assert get_origin(str) is None
assert get_origin(Dict[str, int]) is dict
Expand All @@ -3188,7 +3225,9 @@ Introspection helpers
generic type, the order of ``(Y, Z, ...)`` may be different from the order
of the original arguments ``[Y, Z, ...]`` due to type caching.
Return ``()`` for unsupported objects.
Examples::
Examples:

.. testcode::

assert get_args(int) == ()
assert get_args(Dict[int, str]) == (int, str)
Expand All @@ -3200,14 +3239,20 @@ Introspection helpers

Check if a type is a :class:`TypedDict`.

For example::
For example:

.. testcode::

class Film(TypedDict):
title: str
year: int

is_typeddict(Film) # => True
is_typeddict(list | str) # => False
assert is_typeddict(Film)
assert not is_typeddict(list | str)

# TypedDict is a factory for creating typed dicts,
# not a typed dict itself
assert not is_typeddict(TypedDict)

.. versionadded:: 3.10

Expand Down

0 comments on commit 2cfe778

Please sign in to comment.