diff --git a/docs/source/additional_features.rst b/docs/source/additional_features.rst index fc151598cff0..19e0d4dcce01 100644 --- a/docs/source/additional_features.rst +++ b/docs/source/additional_features.rst @@ -21,10 +21,10 @@ They can be defined using the :py:func:`@dataclasses.dataclass @dataclass class Application: name: str - plugins: List[str] = field(default_factory=list) + plugins: list[str] = field(default_factory=list) test = Application("Testing...") # OK - bad = Application("Testing...", "with plugin") # Error: List[str] expected + bad = Application("Testing...", "with plugin") # Error: list[str] expected Mypy will detect special methods (such as :py:meth:`__lt__ `) depending on the flags used to define dataclasses. For example: diff --git a/docs/source/cheat_sheet_py3.rst b/docs/source/cheat_sheet_py3.rst index 35c60f5a0610..734bc16ddea5 100644 --- a/docs/source/cheat_sheet_py3.rst +++ b/docs/source/cheat_sheet_py3.rst @@ -45,6 +45,7 @@ Built-in types .. code-block:: python + from typing import List, Set, Dict, Tuple, Optional # For simple built-in types, just use the name of the type @@ -60,7 +61,7 @@ Built-in types x: set[int] = {6, 7} # In Python 3.8 and earlier, the name of the collection type is - # capitalized, and the type is imported from 'typing' + # capitalized, and the type is imported from the 'typing' module x: List[int] = [1] x: Set[int] = {6, 7} @@ -68,8 +69,8 @@ Built-in types x = [1] # type: List[int] # For mappings, we need the types of both keys and values - x: dict[str, float] = {'field': 2.0} # Python 3.9+ - x: Dict[str, float] = {'field': 2.0} + x: dict[str, float] = {"field": 2.0} # Python 3.9+ + x: Dict[str, float] = {"field": 2.0} # For tuples of fixed size, we specify the types of all the elements x: tuple[int, str, float] = (3, "yes", 7.5) # Python 3.9+ @@ -95,7 +96,7 @@ Python 3 supports an annotation syntax for function declarations. .. code-block:: python - from typing import Callable, Iterator, Union, Optional, List + from typing import Callable, Iterator, Union, Optional # This is how you annotate a function definition def stringify(num: int) -> str: @@ -121,12 +122,12 @@ Python 3 supports an annotation syntax for function declarations. i += 1 # You can of course split a function annotation over multiple lines - def send_email(address: Union[str, List[str]], + def send_email(address: Union[str, list[str]], sender: str, - cc: Optional[List[str]], - bcc: Optional[List[str]], + cc: Optional[list[str]], + bcc: Optional[list[str]], subject='', - body: Optional[List[str]] = None + body: Optional[list[str]] = None ) -> bool: ... @@ -143,7 +144,7 @@ When you're puzzled or when things are complicated .. code-block:: python - from typing import Union, Any, List, Optional, cast + from typing import Union, Any, Optional, cast # To find out what type mypy infers for an expression anywhere in # your program, wrap it in reveal_type(). Mypy will print an error @@ -151,7 +152,7 @@ When you're puzzled or when things are complicated reveal_type(1) # -> Revealed type is "builtins.int" # Use Union when something could be one of a few types - x: List[Union[int, str]] = [3, 5, "test", "fun"] + x: list[Union[int, str]] = [3, 5, "test", "fun"] # Use Any if you don't know the type of something or it's too # dynamic to write a type for @@ -159,7 +160,7 @@ When you're puzzled or when things are complicated # If you initialize a variable with an empty container or "None" # you may have to help mypy a bit by providing a type annotation - x: List[str] = [] + x: list[str] = [] x: Optional[str] = None # This makes each positional arg and each keyword arg a "str" @@ -176,8 +177,8 @@ When you're puzzled or when things are complicated # "cast" is a helper function that lets you override the inferred # type of an expression. It's only for mypy -- there's no runtime check. a = [4] - b = cast(List[int], a) # Passes fine - c = cast(List[str], a) # Passes fine (no runtime check) + b = cast(list[int], a) # Passes fine + c = cast(list[str], a) # Passes fine (no runtime check) reveal_type(c) # -> Revealed type is "builtins.list[builtins.str]" print(c) # -> [4]; the object is not cast @@ -209,25 +210,25 @@ that are common in idiomatic Python are standardized. .. code-block:: python - from typing import Mapping, MutableMapping, Sequence, Iterable, List, Set + from typing import Mapping, MutableMapping, Sequence, Iterable # Use Iterable for generic iterables (anything usable in "for"), # and Sequence where a sequence (supporting "len" and "__getitem__") is # required - def f(ints: Iterable[int]) -> List[str]: + def f(ints: Iterable[int]) -> list[str]: return [str(x) for x in ints] f(range(1, 3)) # Mapping describes a dict-like object (with "__getitem__") that we won't # mutate, and MutableMapping one (with "__setitem__") that we might - def f(my_mapping: Mapping[int, str]) -> List[int]: + def f(my_mapping: Mapping[int, str]) -> list[int]: my_mapping[5] = 'maybe' # if we try this, mypy will throw an error... return list(my_mapping.keys()) f({3: 'yes', 4: 'no'}) - def f(my_mapping: MutableMapping[int, str]) -> Set[str]: + def f(my_mapping: MutableMapping[int, str]) -> set[str]: my_mapping[5] = 'maybe' # ...but mypy is OK with this. return set(my_mapping.values()) @@ -262,12 +263,12 @@ Classes # You can use the ClassVar annotation to declare a class variable class Car: seats: ClassVar[int] = 4 - passengers: ClassVar[List[str]] + passengers: ClassVar[list[str]] # You can also declare the type of an attribute in "__init__" class Box: def __init__(self) -> None: - self.items: List[str] = [] + self.items: list[str] = [] Coroutines and asyncio diff --git a/docs/source/class_basics.rst b/docs/source/class_basics.rst index 70d2dc631631..83177e26aa67 100644 --- a/docs/source/class_basics.rst +++ b/docs/source/class_basics.rst @@ -33,7 +33,7 @@ a type annotation: .. code-block:: python class A: - x: List[int] # Declare attribute 'x' of type List[int] + x: list[int] # Declare attribute 'x' of type list[int] a = A() a.x = [1] # OK @@ -48,7 +48,7 @@ than 3.6: .. code-block:: python class A: - x = None # type: List[int] # Declare attribute 'x' of type List[int] + x = None # type: list[int] # Declare attribute 'x' of type list[int] Note that attribute definitions in the class body that use a type comment are special: a ``None`` value is valid as the initializer, even though @@ -62,7 +62,7 @@ in a method: class A: def __init__(self) -> None: - self.x: List[int] = [] + self.x: list[int] = [] def f(self) -> None: self.y: Any = 0 @@ -160,7 +160,7 @@ This behavior will change in the future, since it's surprising. .. note:: A :py:data:`~typing.ClassVar` type parameter cannot include type variables: - ``ClassVar[T]`` and ``ClassVar[List[T]]`` + ``ClassVar[T]`` and ``ClassVar[list[T]]`` are both invalid if ``T`` is a type variable (see :ref:`generic-classes` for more about type variables). @@ -200,7 +200,7 @@ override has a compatible signature: You can also vary return types **covariantly** in overriding. For example, you could override the return type ``Iterable[int]`` with a - subtype such as ``List[int]``. Similarly, you can vary argument types + subtype such as ``list[int]``. Similarly, you can vary argument types **contravariantly** -- subclasses can have more general argument types. You can also override a statically typed method with a dynamically diff --git a/docs/source/command_line.rst b/docs/source/command_line.rst index fdf44566c398..64c2f8f03b3e 100644 --- a/docs/source/command_line.rst +++ b/docs/source/command_line.rst @@ -312,9 +312,8 @@ The following options are available: .. option:: --disallow-any-generics This flag disallows usage of generic types that do not specify explicit - type parameters. Moreover, built-in collections (such as :py:class:`list` and - :py:class:`dict`) become disallowed as you should use their aliases from the :py:mod:`typing` - module (such as :py:class:`List[int] ` and :py:class:`Dict[str, str] `). + type parameters. For example you can't use a bare ``x: list``, you must say + ``x: list[int]``. .. option:: --disallow-subclassing-any @@ -521,10 +520,10 @@ of the above sections. .. code-block:: python - def process(items: List[str]) -> None: - # 'items' has type List[str] + def process(items: list[str]) -> None: + # 'items' has type list[str] items = [item.split() for item in items] - # 'items' now has type List[List[str]] + # 'items' now has type list[list[str]] ... .. option:: --local-partial-types @@ -585,9 +584,9 @@ of the above sections. .. code-block:: python - from typing import List, Text + from typing import Text - items: List[int] + items: list[int] if 'some string' in items: # Error: non-overlapping container check! ... diff --git a/docs/source/error_code_list.rst b/docs/source/error_code_list.rst index 13cb464f7984..852913ce79bb 100644 --- a/docs/source/error_code_list.rst +++ b/docs/source/error_code_list.rst @@ -117,15 +117,15 @@ Example: .. code-block:: python - from typing import List, Optional + from typing import Optional - def first(x: List[int]) -> Optional[int]: + def first(x: list[int]) -> Optional[int]: return x[0] if x else 0 - t = (5, 4) - # Error: Argument 1 to "first" has incompatible type "Tuple[int, int]"; - # expected "List[int]" [arg-type] - print(first(t)) + t = (5, 4) + # Error: Argument 1 to "first" has incompatible type "tuple[int, int]"; + # expected "list[int]" [arg-type] + print(first(t)) Check calls to overloaded functions [call-overload] --------------------------------------------------- @@ -171,26 +171,24 @@ This example incorrectly uses the function ``log`` as a type: .. code-block:: python - from typing import List + def log(x: object) -> None: + print('log:', repr(x)) - def log(x: object) -> None: - print('log:', repr(x)) - - # Error: Function "t.log" is not valid as a type [valid-type] - def log_all(objs: List[object], f: log) -> None: - for x in objs: - f(x) + # Error: Function "t.log" is not valid as a type [valid-type] + def log_all(objs: list[object], f: log) -> None: + for x in objs: + f(x) You can use :py:data:`~typing.Callable` as the type for callable objects: .. code-block:: python - from typing import List, Callable + from typing import Callable - # OK - def log_all(objs: List[object], f: Callable[[object], None]) -> None: - for x in objs: - f(x) + # OK + def log_all(objs: list[object], f: Callable[[object], None]) -> None: + for x in objs: + f(x) Require annotation if variable type is unclear [var-annotated] -------------------------------------------------------------- @@ -206,23 +204,21 @@ Example with an error: .. code-block:: python - class Bundle: - def __init__(self) -> None: - # Error: Need type annotation for "items" - # (hint: "items: List[] = ...") [var-annotated] - self.items = [] + class Bundle: + def __init__(self) -> None: + # Error: Need type annotation for "items" + # (hint: "items: list[] = ...") [var-annotated] + self.items = [] - reveal_type(Bundle().items) # list[Any] + reveal_type(Bundle().items) # list[Any] To address this, we add an explicit annotation: .. code-block:: python - from typing import List - - class Bundle: - def __init__(self) -> None: - self.items: List[str] = [] # OK + class Bundle: + def __init__(self) -> None: + self.items: list[str] = [] # OK reveal_type(Bundle().items) # list[str] @@ -377,10 +373,10 @@ Example: a['x'] # OK - # Error: Invalid index type "int" for "Dict[str, int]"; expected type "str" [index] + # Error: Invalid index type "int" for "dict[str, int]"; expected type "str" [index] print(a[1]) - # Error: Invalid index type "bytes" for "Dict[str, int]"; expected type "str" [index] + # Error: Invalid index type "bytes" for "dict[str, int]"; expected type "str" [index] a[b'x'] = 4 Check list items [list-item] @@ -394,10 +390,8 @@ Example: .. code-block:: python - from typing import List - # Error: List item 0 has incompatible type "int"; expected "str" [list-item] - a: List[str] = [0] + a: list[str] = [0] Check dict items [dict-item] ---------------------------- @@ -410,10 +404,8 @@ Example: .. code-block:: python - from typing import Dict - # Error: Dict entry 0 has incompatible type "str": "str"; expected "str": "int" [dict-item] - d: Dict[str, int] = {'key': 'value'} + d: dict[str, int] = {'key': 'value'} Check TypedDict items [typeddict-item] -------------------------------------- diff --git a/docs/source/error_code_list2.rst b/docs/source/error_code_list2.rst index 429302a94277..1e035fcf7f69 100644 --- a/docs/source/error_code_list2.rst +++ b/docs/source/error_code_list2.rst @@ -19,10 +19,10 @@ Check that type arguments exist [type-arg] ------------------------------------------ If you use :option:`--disallow-any-generics `, mypy requires that each generic -type has values for each type argument. For example, the types ``List`` or -``dict`` would be rejected. You should instead use types like ``List[int]`` or -``Dict[str, int]``. Any omitted generic type arguments get implicit ``Any`` -values. The type ``List`` is equivalent to ``List[Any]``, and so on. +type has values for each type argument. For example, the types ``list`` or +``dict`` would be rejected. You should instead use types like ``list[int]`` or +``dict[str, int]``. Any omitted generic type arguments get implicit ``Any`` +values. The type ``list`` is equivalent to ``list[Any]``, and so on. Example: @@ -30,10 +30,8 @@ Example: # mypy: disallow-any-generics - from typing import List - - # Error: Missing type parameters for generic type "List" [type-arg] - def remove_dups(items: List) -> List: + # Error: Missing type parameters for generic type "list" [type-arg] + def remove_dups(items: list) -> list: ... Check that every function has an annotation [no-untyped-def] diff --git a/docs/source/extending_mypy.rst b/docs/source/extending_mypy.rst index 6d5dc79409a8..5c59bef506cc 100644 --- a/docs/source/extending_mypy.rst +++ b/docs/source/extending_mypy.rst @@ -9,10 +9,10 @@ Integrating mypy into another Python application ************************************************ It is possible to integrate mypy into another Python 3 application by -importing ``mypy.api`` and calling the ``run`` function with a parameter of type ``List[str]``, containing +importing ``mypy.api`` and calling the ``run`` function with a parameter of type ``list[str]``, containing what normally would have been the command line arguments to mypy. -Function ``run`` returns a ``Tuple[str, str, int]``, namely +Function ``run`` returns a ``tuple[str, str, int]``, namely ``(, , )``, in which ```` is what mypy normally writes to :py:data:`sys.stdout`, ```` is what mypy normally writes to :py:data:`sys.stderr` and ``exit_status`` is the exit status mypy normally diff --git a/docs/source/final_attrs.rst b/docs/source/final_attrs.rst index 8c42ae9ec56b..e5d209644fce 100644 --- a/docs/source/final_attrs.rst +++ b/docs/source/final_attrs.rst @@ -119,9 +119,9 @@ annotations. Using it in any other position is an error. In particular, .. code-block:: python - x: List[Final[int]] = [] # Error! + x: list[Final[int]] = [] # Error! - def fun(x: Final[List[int]]) -> None: # Error! + def fun(x: Final[list[int]]) -> None: # Error! ... ``Final`` and :py:data:`~typing.ClassVar` should not be used together. Mypy will infer diff --git a/docs/source/getting_started.rst b/docs/source/getting_started.rst index 12dfba2add93..f9b21d8dbf60 100644 --- a/docs/source/getting_started.rst +++ b/docs/source/getting_started.rst @@ -153,8 +153,8 @@ Arguments with default values can be annotated like so: .. code-block:: python def stars(*args: int, **kwargs: float) -> None: - # 'args' has type 'Tuple[int, ...]' (a tuple of ints) - # 'kwargs' has type 'Dict[str, float]' (a dict of strs to floats) + # 'args' has type 'tuple[int, ...]' (a tuple of ints) + # 'kwargs' has type 'dict[str, float]' (a dict of strs to floats) for arg in args: print(arg) for key, value in kwargs: @@ -182,8 +182,8 @@ strings, use the ``list[str]`` type (Python 3.9 and later): greet_all(names) # Ok! greet_all(ages) # Error due to incompatible types -The ``list`` type is an example of something called a *generic type*: it can -accept one or more *type parameters*. In this case, we *parameterized* ``list`` +The :py:class:`list` type is an example of something called a *generic type*: it can +accept one or more *type parameters*. In this case, we *parameterized* :py:class:`list` by writing ``list[str]``. This lets mypy know that ``greet_all`` accepts specifically lists containing strings, and not lists containing ints or any other type. @@ -207,9 +207,8 @@ After all, there's no reason why this function must accept *specifically* a list it would run just fine if you were to pass in a tuple, a set, or any other custom iterable. You can express this idea using the -:py:class:`collections.abc.Iterable` type instead of -:py:class:`~typing.List` (or :py:class:`typing.Iterable` in Python -3.8 and earlier): +:py:class:`collections.abc.Iterable` (or :py:class:`typing.Iterable` in Python +3.8 and earlier) type instead of :py:class:`list` : .. code-block:: python @@ -268,7 +267,7 @@ generic types or your own type aliases) by looking through the In some examples we use capitalized variants of types, such as ``List``, and sometimes we use plain ``list``. They are equivalent, - but the prior variant is needed if you are not using a recent Python. + but the prior variant is needed if you are using Python 3.8 or earlier. Local type inference ******************** @@ -286,7 +285,7 @@ in that if statement. As another example, consider the following function. Mypy can type check this function without a problem: it will use the available context and deduce that ``output`` must be -of type ``List[float]`` and that ``num`` must be of type ``float``: +of type ``list[float]`` and that ``num`` must be of type ``float``: .. code-block:: python diff --git a/docs/source/kinds_of_types.rst b/docs/source/kinds_of_types.rst index f691bc899339..b1b6648b0c1c 100644 --- a/docs/source/kinds_of_types.rst +++ b/docs/source/kinds_of_types.rst @@ -108,23 +108,24 @@ The ``Any`` type is discussed in more detail in section :ref:`dynamic-typing`. Tuple types *********** -The type ``Tuple[T1, ..., Tn]`` represents a tuple with the item types ``T1``, ..., ``Tn``: +The type ``tuple[T1, ..., Tn]`` represents a tuple with the item types ``T1``, ..., ``Tn``: .. code-block:: python - def f(t: Tuple[int, str]) -> None: + # Use `typing.Tuple` in Python 3.8 and earlier + def f(t: tuple[int, str]) -> None: t = 1, 'foo' # OK t = 'foo', 1 # Type check error A tuple type of this kind has exactly a specific number of items (2 in the above example). Tuples can also be used as immutable, -varying-length sequences. You can use the type ``Tuple[T, ...]`` (with +varying-length sequences. You can use the type ``tuple[T, ...]`` (with a literal ``...`` -- it's part of the syntax) for this purpose. Example: .. code-block:: python - def print_squared(t: Tuple[int, ...]) -> None: + def print_squared(t: tuple[int, ...]) -> None: for n in t: print(n, n ** 2) @@ -134,12 +135,12 @@ purpose. Example: .. note:: - Usually it's a better idea to use ``Sequence[T]`` instead of ``Tuple[T, ...]``, as + Usually it's a better idea to use ``Sequence[T]`` instead of ``tuple[T, ...]``, as :py:class:`~typing.Sequence` is also compatible with lists and other non-tuple sequences. .. note:: - ``Tuple[...]`` is valid as a base class in Python 3.6 and later, and + ``tuple[...]`` is valid as a base class in Python 3.6 and later, and always in stub files. In earlier Python versions you can sometimes work around this limitation by using a named tuple as a base class (see section :ref:`named-tuples`). @@ -194,7 +195,7 @@ using bidirectional type inference: .. code-block:: python - l = map(lambda x: x + 1, [1, 2, 3]) # Infer x as int and l as List[int] + l = map(lambda x: x + 1, [1, 2, 3]) # Infer x as int and l as list[int] If you want to give the argument or return value types explicitly, use an ordinary, perhaps nested function definition. @@ -353,20 +354,17 @@ and ``None`` is used as a dummy, placeholder initializer: .. code-block:: python - from typing import List - class Container: - items = None # type: List[str] # OK (only with type comment) + items = None # type: list[str] # OK (only with type comment) This is not a problem when using variable annotations, since no initializer is needed: .. code-block:: python - from typing import List class Container: - items: List[str] # No initializer + items: list[str] # No initializer Mypy generally uses the first assignment to a variable to infer the type of the variable. However, if you assign both a ``None`` @@ -419,8 +417,6 @@ the runtime with some limitations (see :ref:`runtime_troubles`). .. code-block:: python - from typing import List - t1: int | str # equivalent to Union[int, str] t2: int | None # equivalent to Optional[int] @@ -505,7 +501,7 @@ In certain situations, type names may end up being long and painful to type: .. code-block:: python - def f() -> Union[List[Dict[Tuple[int, str], Set[int]]], Tuple[str, List[str]]]: + def f() -> Union[list[dict[tuple[int, str], set[int]]], tuple[str, list[str]]]: ... When cases like this arise, you can define a type alias by simply @@ -513,7 +509,7 @@ assigning the type to a variable: .. code-block:: python - AliasType = Union[List[Dict[Tuple[int, str], Set[int]]], Tuple[str, List[str]]] + AliasType = Union[list[dict[tuple[int, str], set[int]]], tuple[str, list[str]]] # Now we can use AliasType in place of the full name: diff --git a/docs/source/literal_types.rst b/docs/source/literal_types.rst index 216313b6c20e..94eec06236ca 100644 --- a/docs/source/literal_types.rst +++ b/docs/source/literal_types.rst @@ -152,16 +152,16 @@ For example, compare and contrast what happens when you try appending these type a: Final = 19 b: Literal[19] = 19 - # Mypy will chose to infer List[int] here. + # Mypy will choose to infer list[int] here. list_of_ints = [] list_of_ints.append(a) - reveal_type(list_of_ints) # Revealed type is "List[int]" + reveal_type(list_of_ints) # Revealed type is "list[int]" # But if the variable you're appending is an explicit Literal, mypy - # will infer List[Literal[19]]. + # will infer list[Literal[19]]. list_of_lits = [] list_of_lits.append(b) - reveal_type(list_of_lits) # Revealed type is "List[Literal[19]]" + reveal_type(list_of_lits) # Revealed type is "list[Literal[19]]" Intelligent indexing diff --git a/docs/source/more_types.rst b/docs/source/more_types.rst index a240ac338988..7b7a5f8dd865 100644 --- a/docs/source/more_types.rst +++ b/docs/source/more_types.rst @@ -355,13 +355,15 @@ program: .. code-block:: python - from typing import List, overload + # For Python 3.8 and below you must use `typing.List` instead of `list`. e.g. + # from typing import List + from typing import overload @overload - def summarize(data: List[int]) -> float: ... + def summarize(data: list[int]) -> float: ... @overload - def summarize(data: List[str]) -> str: ... + def summarize(data: list[str]) -> str: ... def summarize(data): if not data: @@ -375,7 +377,7 @@ program: output = summarize([]) The ``summarize([])`` call matches both variants: an empty list could -be either a ``List[int]`` or a ``List[str]``. In this case, mypy +be either a ``list[int]`` or a ``list[str]``. In this case, mypy will break the tie by picking the first matching variant: ``output`` will have an inferred type of ``float``. The implementor is responsible for making sure ``summarize`` breaks ties in the same way at runtime. @@ -397,7 +399,7 @@ matching variant returns: .. code-block:: python - some_list: Union[List[int], List[str]] + some_list: Union[list[int], list[str]] # output3 is of type 'Union[float, str]' output3 = summarize(some_list) @@ -524,7 +526,7 @@ suppose we modify the above snippet so it calls ``summarize`` instead of .. code-block:: python - some_list: List[str] = [] + some_list: list[str] = [] summarize(some_list) + "danger danger" # Type safe, yet crashes at runtime! We run into a similar issue here. This program type checks if we look just at the @@ -571,7 +573,7 @@ with ``Union[int, slice]`` and ``Union[T, Sequence]``. Previously, mypy used to perform type erasure on all overload variants. For example, the ``summarize`` example from the previous section used to be - illegal because ``List[str]`` and ``List[int]`` both erased to just ``List[Any]``. + illegal because ``list[str]`` and ``list[int]`` both erased to just ``list[Any]``. This restriction was removed in mypy 0.620. Mypy also previously used to select the best matching variant using a different @@ -623,7 +625,7 @@ argument is itself generic: def first_chunk(self: Storage[Sequence[S]]) -> S: return self.content[0] - page: Storage[List[str]] + page: Storage[list[str]] page.first_chunk() # OK, type is "str" Storage(0).first_chunk() # Error: Invalid self argument "Storage[int]" to attribute function @@ -708,13 +710,13 @@ classes are generic, self-type allows giving them precise signatures: self.item = item @classmethod - def make_pair(cls: Type[Q], item: T) -> Tuple[Q, Q]: + def make_pair(cls: Type[Q], item: T) -> tuple[Q, Q]: return cls(item), cls(item) class Sub(Base[T]): ... - pair = Sub.make_pair('yes') # Type is "Tuple[Sub[str], Sub[str]]" + pair = Sub.make_pair('yes') # Type is "tuple[Sub[str], Sub[str]]" bad = Sub[int].make_pair('no') # Error: Argument 1 to "make_pair" of "Base" # has incompatible type "str"; expected "int" @@ -906,7 +908,7 @@ Here is a typical example: Only a fixed set of string keys is expected (``'name'`` and ``'year'`` above), and each key has an independent value type (``str`` for ``'name'`` and ``int`` for ``'year'`` above). We've previously -seen the ``Dict[K, V]`` type, which lets you declare uniform +seen the ``dict[K, V]`` type, which lets you declare uniform dictionary types, where every value has the same type, and arbitrary keys are supported. This is clearly not a good fit for ``movie`` above. Instead, you can use a ``TypedDict`` to give a precise @@ -925,7 +927,7 @@ dictionary value depends on the key: and ``'year'`` (with type ``int``). Note that we used an explicit type annotation for the ``movie`` variable. This type annotation is important -- without it, mypy will try to infer a regular, uniform -:py:class:`~typing.Dict` type for ``movie``, which is not what we want here. +:py:class:`dict` type for ``movie``, which is not what we want here. .. note:: @@ -934,7 +936,7 @@ important -- without it, mypy will try to infer a regular, uniform desired type based on the declared argument type. Also, if an assignment target has been previously defined, and it has a ``TypedDict`` type, mypy will treat the assigned value as a ``TypedDict``, - not :py:class:`~typing.Dict`. + not :py:class:`dict`. Now mypy will recognize these as valid: @@ -975,8 +977,8 @@ extra items is compatible with (a subtype of) a narrower ``TypedDict``, assuming item types are compatible (*totality* also affects subtyping, as discussed below). -A ``TypedDict`` object is not a subtype of the regular ``Dict[...]`` -type (and vice versa), since :py:class:`~typing.Dict` allows arbitrary keys to be +A ``TypedDict`` object is not a subtype of the regular ``dict[...]`` +type (and vice versa), since :py:class:`dict` allows arbitrary keys to be added and removed, unlike ``TypedDict``. However, any ``TypedDict`` object is a subtype of (that is, compatible with) ``Mapping[str, object]``, since :py:class:`~typing.Mapping` only provides read-only access to the dictionary items: diff --git a/docs/source/protocols.rst b/docs/source/protocols.rst index 38d1ee9bf357..cd59f841d8a0 100644 --- a/docs/source/protocols.rst +++ b/docs/source/protocols.rst @@ -455,19 +455,19 @@ member: .. code-block:: python - from typing import Optional, Iterable, List + from typing import Optional, Iterable from typing_extensions import Protocol class Combiner(Protocol): - def __call__(self, *vals: bytes, maxlen: Optional[int] = None) -> List[bytes]: ... + def __call__(self, *vals: bytes, maxlen: Optional[int] = None) -> list[bytes]: ... def batch_proc(data: Iterable[bytes], cb_results: Combiner) -> bytes: for item in data: ... - def good_cb(*vals: bytes, maxlen: Optional[int] = None) -> List[bytes]: + def good_cb(*vals: bytes, maxlen: Optional[int] = None) -> list[bytes]: ... - def bad_cb(*vals: bytes, maxitems: Optional[int]) -> List[bytes]: + def bad_cb(*vals: bytes, maxitems: Optional[int]) -> list[bytes]: ... batch_proc([], good_cb) # OK diff --git a/docs/source/running_mypy.rst b/docs/source/running_mypy.rst index ef764ffd6dc0..d1c701e27e5a 100644 --- a/docs/source/running_mypy.rst +++ b/docs/source/running_mypy.rst @@ -81,7 +81,7 @@ Note that if you use namespace packages (in particular, packages without $ mypy -c 'x = [1, 2]; print(x())' ...will type check the above string as a mini-program (and in this case, - will report that ``List[int]`` is not callable). + will report that ``list[int]`` is not callable). Reading a list of files from a file diff --git a/docs/source/runtime_troubles.rst b/docs/source/runtime_troubles.rst index 863d0c9c85eb..e748fb000b71 100644 --- a/docs/source/runtime_troubles.rst +++ b/docs/source/runtime_troubles.rst @@ -30,7 +30,7 @@ string-literal types with non-string-literal types freely: .. code-block:: python - def f(a: List['A']) -> None: ... # OK + def f(a: list['A']) -> None: ... # OK def g(n: 'int') -> None: ... # OK, though not useful class A: pass @@ -70,7 +70,7 @@ required to be valid Python syntax. For more details, see :pep:`563`. # base class example from __future__ import annotations - class A(Tuple['B', 'C']): ... # String literal types needed here + class A(tuple['B', 'C']): ... # String literal types needed here class B: ... class C: ... @@ -156,23 +156,22 @@ File ``foo.py``: .. code-block:: python - from typing import List, TYPE_CHECKING + from typing import TYPE_CHECKING if TYPE_CHECKING: import bar - def listify(arg: 'bar.BarClass') -> 'List[bar.BarClass]': + def listify(arg: 'bar.BarClass') -> 'list[bar.BarClass]': return [arg] File ``bar.py``: .. code-block:: python - from typing import List from foo import listify class BarClass: - def listifyme(self) -> 'List[BarClass]': + def listifyme(self) -> 'list[BarClass]': return listify(self) .. _not-generic-runtime: diff --git a/docs/source/stubs.rst b/docs/source/stubs.rst index a15c16d85da3..6084243dc506 100644 --- a/docs/source/stubs.rst +++ b/docs/source/stubs.rst @@ -112,22 +112,21 @@ For example: .. code-block:: python - from typing import List from typing_extensions import Protocol class Resource(Protocol): - def ok_1(self, foo: List[str] = ...) -> None: ... + def ok_1(self, foo: list[str] = ...) -> None: ... - def ok_2(self, foo: List[str] = ...) -> None: + def ok_2(self, foo: list[str] = ...) -> None: raise NotImplementedError() - def ok_3(self, foo: List[str] = ...) -> None: + def ok_3(self, foo: list[str] = ...) -> None: """Some docstring""" pass # Error: Incompatible default for argument "foo" (default has - # type "ellipsis", argument has type "List[str]") - def not_ok(self, foo: List[str] = ...) -> None: + # type "ellipsis", argument has type "list[str]") + def not_ok(self, foo: list[str] = ...) -> None: print(foo) .. note:: diff --git a/docs/source/type_inference_and_annotations.rst b/docs/source/type_inference_and_annotations.rst index cba505d4bf71..80b9356cd681 100644 --- a/docs/source/type_inference_and_annotations.rst +++ b/docs/source/type_inference_and_annotations.rst @@ -12,7 +12,7 @@ static type of the value expression: .. code-block:: python i = 1 # Infer type "int" for i - l = [1, 2] # Infer type "List[int]" for l + l = [1, 2] # Infer type "list[int]" for l Type inference is not used in dynamically typed functions (those without a function type annotation) — every local variable type defaults @@ -84,24 +84,32 @@ In these cases you can give the type explicitly using a type annotation: .. code-block:: python - l: List[int] = [] # Create empty list with type List[int] - d: Dict[str, int] = {} # Create empty dictionary (str -> int) + l: list[int] = [] # Create empty list with type list[int] + d: dict[str, int] = {} # Create empty dictionary (str -> int) Similarly, you can also give an explicit type when creating an empty set: .. code-block:: python - s: Set[int] = set() + s: set[int] = set() + +.. note:: + + Using type annotations (e.g. `list[int]`) on builtin collections like + :py:class:`list`, :py:class:`dict`, :py:class:`tuple`, and :py:class:`set` + only works in Python 3.9 and later. For Python 3.8 and earlier, you must use + :py:class:`~typing.List`, :py:class:`~typing.Dict`, etc. + Compatibility of container types ******************************** -The following program generates a mypy error, since ``List[int]`` -is not compatible with ``List[object]``: +The following program generates a mypy error, since ``list[int]`` +is not compatible with ``list[object]``: .. code-block:: python - def f(l: List[object], k: List[int]) -> None: + def f(l: list[object], k: list[int]) -> None: l = k # Type check error: incompatible types in assignment The reason why the above assignment is disallowed is that allowing the @@ -109,12 +117,12 @@ assignment could result in non-int values stored in a list of ``int``: .. code-block:: python - def f(l: List[object], k: List[int]) -> None: + def f(l: list[object], k: list[int]) -> None: l = k l.append('x') - print(k[-1]) # Ouch; a string in List[int] + print(k[-1]) # Ouch; a string in list[int] -Other container types like :py:class:`~typing.Dict` and :py:class:`~typing.Set` behave similarly. We +Other container types like :py:class:`dict` and :py:class:`set` behave similarly. We will discuss how you can work around this in :ref:`variance`. You can still run the above program; it prints ``x``. This illustrates @@ -132,23 +140,23 @@ example, the following is valid: .. code-block:: python - def f(l: List[object]) -> None: - l = [1, 2] # Infer type List[object] for [1, 2], not List[int] + def f(l: list[object]) -> None: + l = [1, 2] # Infer type list[object] for [1, 2], not list[int] In an assignment, the type context is determined by the assignment target. In this case this is ``l``, which has the type -``List[object]``. The value expression ``[1, 2]`` is type checked in -this context and given the type ``List[object]``. In the previous +``list[object]``. The value expression ``[1, 2]`` is type checked in +this context and given the type ``list[object]``. In the previous example we introduced a new variable ``l``, and here the type context was empty. Declared argument types are also used for type context. In this program -mypy knows that the empty list ``[]`` should have type ``List[int]`` based +mypy knows that the empty list ``[]`` should have type ``list[int]`` based on the declared type of ``arg`` in ``foo``: .. code-block:: python - def foo(arg: List[int]) -> None: + def foo(arg: list[int]) -> None: print('Items:', ''.join(str(a) for a in arg)) foo([]) # OK @@ -159,7 +167,7 @@ in the following statement: .. code-block:: python - def foo(arg: List[int]) -> None: + def foo(arg: list[int]) -> None: print('Items:', ', '.join(arg)) a = [] # Error: Need type annotation for "a" @@ -170,7 +178,7 @@ Working around the issue is easy by adding a type annotation: .. code-block:: Python ... - a: List[int] = [] # OK + a: list[int] = [] # OK foo(a) Declaring multiple variable types at a time @@ -206,16 +214,16 @@ right-hand side of an assignment, but not always: p, q, *rs = 1, 2 # Error: Type of rs cannot be inferred On first line, the type of ``bs`` is inferred to be -``List[int]``. However, on the second line, mypy cannot infer the type +``list[int]``. However, on the second line, mypy cannot infer the type of ``rs``, because there is no right-hand side value for ``rs`` to infer the type from. In cases like these, the starred expression needs to be annotated with a starred type: .. code-block:: python - p, q, *rs = 1, 2 # type: int, int, List[int] + p, q, *rs = 1, 2 # type: int, int, list[int] -Here, the type of ``rs`` is set to ``List[int]``. +Here, the type of ``rs`` is set to ``list[int]``. Silencing type errors ********************* diff --git a/docs/source/type_narrowing.rst b/docs/source/type_narrowing.rst index 6e6e442e4ad5..b5f297d283c0 100644 --- a/docs/source/type_narrowing.rst +++ b/docs/source/type_narrowing.rst @@ -148,11 +148,11 @@ to perform a cast: .. code-block:: python - from typing import cast, List + from typing import cast o: object = [1] - x = cast(List[int], o) # OK - y = cast(List[str], o) # OK (cast performs no actual runtime check) + x = cast(list[int], o) # OK + y = cast(list[str], o) # OK (cast performs no actual runtime check) To support runtime checking of casts such as the above, we'd have to check the types of all list items, which would be very inefficient for large lists. @@ -201,35 +201,32 @@ Let's have a look at the regular ``bool`` example: .. code-block:: python - from typing import List - - def is_str_list(val: List[object]) -> bool: + def is_str_list(val: list[object]) -> bool: """Determines whether all objects in the list are strings""" return all(isinstance(x, str) for x in val) - def func1(val: List[object]) -> None: + def func1(val: list[object]) -> None: if is_str_list(val): - reveal_type(val) # Reveals List[object] + reveal_type(val) # Reveals list[object] print(" ".join(val)) # Error: incompatible type The same example with ``TypeGuard``: .. code-block:: python - from typing import List from typing import TypeGuard # use `typing_extensions` for Python 3.9 and below - def is_str_list(val: List[object]) -> TypeGuard[List[str]]: + def is_str_list(val: list[object]) -> TypeGuard[list[str]]: """Determines whether all objects in the list are strings""" return all(isinstance(x, str) for x in val) - def func1(val: List[object]) -> None: + def func1(val: list[object]) -> None: if is_str_list(val): - reveal_type(val) # List[str] + reveal_type(val) # list[str] print(" ".join(val)) # ok How does it work? ``TypeGuard`` narrows the first function argument (``val``) -to the type specified as the first type parameter (``List[str]``). +to the type specified as the first type parameter (``list[str]``). .. note:: @@ -260,19 +257,19 @@ Generic TypeGuards .. code-block:: python - from typing import Tuple, TypeVar + from typing import TypeVar from typing import TypeGuard # use `typing_extensions` for `python<3.10` _T = TypeVar("_T") - def is_two_element_tuple(val: Tuple[_T, ...]) -> TypeGuard[Tuple[_T, _T]]: + def is_two_element_tuple(val: tuple[_T, ...]) -> TypeGuard[tuple[_T, _T]]: return len(val) == 2 - def func(names: Tuple[str, ...]): + def func(names: tuple[str, ...]): if is_two_element_tuple(names): - reveal_type(names) # Tuple[str, str] + reveal_type(names) # tuple[str, str] else: - reveal_type(names) # Tuple[str, ...] + reveal_type(names) # tuple[str, ...] Typeguards with parameters ~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -281,17 +278,17 @@ Type guard functions can accept extra arguments: .. code-block:: python - from typing import Type, Set, TypeVar + from typing import Type, TypeVar from typing import TypeGuard # use `typing_extensions` for `python<3.10` _T = TypeVar("_T") - def is_set_of(val: Set[Any], type: Type[_T]) -> TypeGuard[Set[_T]]: + def is_set_of(val: set[Any], type: Type[_T]) -> TypeGuard[set[_T]]: return all(isinstance(x, type) for x in val) - items: Set[Any] + items: set[Any] if is_set_of(items, str): - reveal_type(items) # Set[str] + reveal_type(items) # set[str] TypeGuards as methods ~~~~~~~~~~~~~~~~~~~~~