diff --git a/docs/spec/annotations.rst b/docs/spec/annotations.rst index 0b5387905..0d4260fee 100644 --- a/docs/spec/annotations.rst +++ b/docs/spec/annotations.rst @@ -19,6 +19,8 @@ This states that the expected type of the ``name`` argument is Expressions whose type is a subtype of a specific argument type are also accepted for that argument. +.. _`missing-annotations`: + Any function without annotations should be treated as having the most general type possible, or ignored, by any type checker. @@ -222,6 +224,8 @@ types cannot be specified:: else: return asyncio.Future(...) +.. _`annotating-methods`: + Annotating instance and class methods ------------------------------------- diff --git a/docs/spec/callables.rst b/docs/spec/callables.rst index 7785cb553..c401ba542 100644 --- a/docs/spec/callables.rst +++ b/docs/spec/callables.rst @@ -17,6 +17,8 @@ What should the default value look like? Any of the options ``""``, In such cases the default value may be specified as a literal ellipsis, i.e. the above example is literally what you would write. +.. _`annotating-args-kwargs`: + Annotating ``*args`` and ``**kwargs`` ------------------------------------- @@ -383,7 +385,7 @@ Callback protocols Protocols can be used to define flexible callback types that are hard (or even impossible) to express using the ``Callable[...]`` syntax -specified by :pep:`484`, such as variadic, overloaded, and complex generic +as specified :ref:`above `, such as variadic, overloaded, and complex generic callbacks. They can be defined as protocols with a ``__call__`` member:: from typing import Protocol diff --git a/docs/spec/dataclasses.rst b/docs/spec/dataclasses.rst index b2466fef1..feeabdead 100644 --- a/docs/spec/dataclasses.rst +++ b/docs/spec/dataclasses.rst @@ -19,7 +19,7 @@ Specification ^^^^^^^^^^^^^ This specification describes a decorator function in -the ``typing`` module named ``dataclass_transform``. This decorator +the :py:mod:`typing` module named :py:func:`~typing.dataclass_transform`. This decorator can be applied to either a function that is itself a decorator, a class, or a metaclass. The presence of ``dataclass_transform`` tells a static type checker that the decorated @@ -333,7 +333,7 @@ meanings of the parameters that must be understood for static type checkers. These standardized parameters must be keyword-only. These parameters are a superset of those supported by -``dataclasses.field``, excluding those that do not have an impact on +:py:func:`dataclasses.field`, excluding those that do not have an impact on type checking such as ``compare`` and ``hash``. Field specifier classes are allowed to use other @@ -436,7 +436,7 @@ Except where stated otherwise, classes impacted by ``dataclass_transform``, either by inheriting from a class that is decorated with ``dataclass_transform`` or by being decorated with a function decorated with ``dataclass_transform``, are assumed to -behave like stdlib ``dataclass``. +behave like stdlib :func:`~dataclasses.dataclass`. This includes, but is not limited to, the following semantics: @@ -488,7 +488,7 @@ This includes, but is not limited to, the following semantics: wheel_count: int * Field ordering and inheritance is assumed to follow the rules - specified in :pep:`557 <557#inheritance>`. This includes the effects of + specified in `the Python docs `. This includes the effects of overrides (redefining a field in a child class that has already been defined in a parent class). diff --git a/docs/spec/directives.rst b/docs/spec/directives.rst index 7070b05b9..4657b1041 100644 --- a/docs/spec/directives.rst +++ b/docs/spec/directives.rst @@ -200,7 +200,7 @@ For deprecated classes and functions, this includes: setter of a property is marked deprecated, attempts to set the property should trigger a diagnostic. -If a method is marked with the :func:`typing.override` decorator from :pep:`698` +If a method is marked with the :ref:`@override decorator ` and the base class method it overrides is deprecated, the type checker should produce a diagnostic. @@ -208,7 +208,7 @@ There are additional scenarios where deprecations could come into play. For example, an object may implement a :class:`typing.Protocol`, but one of the methods required for protocol compliance is deprecated. As scenarios such as this one appear complex and relatively unlikely to come up in practice, -this PEP does not mandate that type checkers detect them. +type checkers are not mandated to detect them. Example ^^^^^^^ diff --git a/docs/spec/generics.rst b/docs/spec/generics.rst index ee2fac6a7..dc9fea648 100644 --- a/docs/spec/generics.rst +++ b/docs/spec/generics.rst @@ -1300,7 +1300,8 @@ hinder them when migrating a legacy code base to use ``TypeVarTuple``. ``*args`` as a Type Variable Tuple ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -:pep:`484` states that when a type annotation is provided for ``*args``, every argument +:ref:`this specification ` states that when a +type annotation is provided for ``*args``, every argument must be of the type annotated. That is, if we specify ``*args`` to be type ``int``, then *all* arguments must be of type ``int``. This limits our ability to specify the type signatures of functions that take heterogeneous argument types. @@ -1338,8 +1339,8 @@ Note that this is different to as this would make ``env`` a keyword-only argument. Using an unpacked unbounded tuple is equivalent to the -:pep:`484#arbitrary-argument-lists-and-default-argument-values` -behavior of ``*args: int``, which accepts zero or +:ref:`behavior ` +of ``*args: int``, which accepts zero or more values of type ``int``: :: diff --git a/docs/spec/literal.rst b/docs/spec/literal.rst index c0d39b98f..d0ca618c6 100644 --- a/docs/spec/literal.rst +++ b/docs/spec/literal.rst @@ -34,7 +34,7 @@ it’s safe to do things like ``foo + 5`` since ``foo`` inherits ``int``’s ``__add__`` method. The resulting type of ``foo + 5`` is ``int``. This "inheriting" behavior is identical to how we -:pep:`handle NewTypes <484#newtype-helper-function>`. +:ref:`handle NewTypes `. Equivalence of two Literals """"""""""""""""""""""""""" @@ -163,7 +163,7 @@ The following parameters are intentionally disallowed by design: ``Literal["foo".replace("o", "b")]``. - Rationale: Literal types are meant to be a - minimal extension to the :pep:`484` typing ecosystem and requiring type + minimal extension to the typing ecosystem and requiring type checkers to interpret potentially expressions inside types adds too much complexity. @@ -442,7 +442,7 @@ Interactions with enums and exhaustiveness checks """"""""""""""""""""""""""""""""""""""""""""""""" Type checkers should be capable of performing exhaustiveness checks when -working Literal types that have a closed number of variants, such as +working with Literal types that have a closed number of variants, such as enums. For example, the type checker should be capable of inferring that the final ``else`` statement must be of type ``str``, since all three values of the ``Status`` enum have already been exhausted:: @@ -463,19 +463,7 @@ values of the ``Status`` enum have already been exhausted:: # 's' must be of type 'str' since all other options are exhausted print("Got custom status: " + s) -The interaction described above is not new: it's already -:pep:`codified within PEP 484 <484#support-for-singleton-types-in-unions>`. -However, many type -checkers (such as mypy) do not yet implement this due to the expected -complexity of the implementation work. - -Some of this complexity will be alleviated once Literal types are introduced: -rather than entirely special-casing enums, we can instead treat them as being -approximately equivalent to the union of their values and take advantage of any -existing logic regarding unions, exhaustibility, type narrowing, reachability, -and so forth the type checker might have already implemented. - -So here, the ``Status`` enum could be treated as being approximately equivalent +Here, the ``Status`` enum could be treated as being approximately equivalent to ``Literal[Status.SUCCESS, Status.INVALID_DATA, Status.FATAL_ERROR]`` and the type of ``s`` narrowed accordingly. diff --git a/docs/spec/protocol.rst b/docs/spec/protocol.rst index 30ffbcca5..c07642445 100644 --- a/docs/spec/protocol.rst +++ b/docs/spec/protocol.rst @@ -29,7 +29,7 @@ with a protocol. If a class is compatible with a protocol but the protocol is not included in the MRO, the class is an *implicit* subtype of the protocol. (Note that one can explicitly subclass a protocol and still not implement it if a protocol attribute is set to ``None`` -in the subclass, see Python `data model `_ +in the subclass, see Python :py:ref:`data model ` for details.) The attributes (variables and methods) of a protocol that are mandatory @@ -86,7 +86,7 @@ Protocol members All methods defined in the protocol class body are protocol members, both normal and decorated with ``@abstractmethod``. If any parameters of a protocol method are not annotated, then their types are assumed to be ``Any`` -(see :pep:`484`). Bodies of protocol methods are type checked. +(see :ref:`"The meaning of annotations" `). Bodies of protocol methods are type checked. An abstract method that should not be called via ``super()`` ought to raise ``NotImplementedError``. Example:: @@ -104,7 +104,7 @@ An abstract method that should not be called via ``super()`` ought to raise Static methods, class methods, and properties are equally allowed in protocols. -To define a protocol variable, one can use :pep:`526` variable +To define a protocol variable, one can use variable annotations in the class body. Additional attributes *only* defined in the body of a method by assignment via ``self`` are not allowed. The rationale for this is that the protocol class implementation is often not shared by @@ -131,8 +131,8 @@ Examples:: var: Template = Concrete('value', 42) # OK To distinguish between protocol class variables and protocol instance -variables, the special ``ClassVar`` annotation should be used as specified -by :pep:`526`. By default, protocol variables as defined above are considered +variables, the special :ref:`ClassVar ` annotation should be used. +By default, protocol variables as defined above are considered readable and writable. To define a read-only protocol variable, one can use an (abstract) property. @@ -320,7 +320,7 @@ Recursive protocols ^^^^^^^^^^^^^^^^^^^ Recursive protocols are also supported. Forward references to the protocol -class names can be given as strings as specified by :pep:`484`. Recursive +class names can be :ref:`given as strings `. Recursive protocols are useful for representing self-referential data structures like trees in an abstract fashion:: @@ -352,8 +352,7 @@ Self-types in protocols ^^^^^^^^^^^^^^^^^^^^^^^ The self-types in protocols follow the -:pep:`corresponding specification <484#annotating-instance-and-class-methods>` -of :pep:`484`. For example:: +:ref:`rules for other methods `. For example:: C = TypeVar('C', bound='Copyable') class Copyable(Protocol): diff --git a/docs/spec/typeddict.rst b/docs/spec/typeddict.rst index 2cf68744e..30850190e 100644 --- a/docs/spec/typeddict.rst +++ b/docs/spec/typeddict.rst @@ -148,18 +148,18 @@ are the only uses of the type a type checker is expected to allow: In particular, TypedDict type objects cannot be used in ``isinstance()`` tests such as ``isinstance(d, Movie)``. The reason is that there is no existing support for checking types of dictionary -item values, since ``isinstance()`` does not work with many :pep:`484` -types, including common ones like ``List[str]``. This would be needed +item values, since ``isinstance()`` does not work with many +types, including common ones like ``list[str]``. This would be needed for cases like this:: class Strings(TypedDict): - items: List[str] + items: list[str] print(isinstance({'items': [1]}, Strings)) # Should be False print(isinstance({'items': ['x']}, Strings)) # Should be True The above use case is not supported. This is consistent with how -``isinstance()`` is not supported for ``List[str]``. +``isinstance()`` is not supported for ``list[str]``. Inheritance @@ -255,6 +255,7 @@ it possible to have a combination of required and non-required keys in a single TypedDict type. Alternatively, ``Required`` and ``NotRequired`` (see below) can be used to mark individual items as required or non-required. +.. _typeddict-functional-syntax: Alternative Syntax ^^^^^^^^^^^^^^^^^^ @@ -490,7 +491,7 @@ alternative is to generate false positive errors for idiomatic code. Use of Final Values and Literal Types ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Type checkers should allow final names (:pep:`591`) with +Type checkers should allow :ref:`final names ` with string values to be used instead of string literals in operations on TypedDict objects. For example, this is valid:: @@ -499,8 +500,8 @@ TypedDict objects. For example, this is valid:: m: Movie = {'name': 'Alien', 'year': 1979} years_since_epoch = m[YEAR] - 1970 -Similarly, an expression with a suitable literal type -(:pep:`586`) can be used instead of a literal value:: +Similarly, an expression with a suitable :ref:`literal type ` +can be used instead of a literal value:: def get_value(movie: Movie, key: Literal['year', 'name']) -> int | str: @@ -577,7 +578,7 @@ Type checkers must enforce this restriction. The runtime implementations of ``Required[]`` and ``NotRequired[]`` may also enforce this restriction. -The :pep:`alternative functional syntax <589#alternative-syntax>` +The :ref:`alternative functional syntax ` for TypedDict also supports ``Required[]``, ``NotRequired[]``, and ``ReadOnly[]``: @@ -589,7 +590,7 @@ for TypedDict also supports Interaction with ``total=False`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Any :pep:`589`-style TypedDict declared with ``total=False`` is equivalent +Any TypedDict declared with ``total=False`` is equivalent to a TypedDict with an implicit ``total=True`` definition with all of its keys marked as ``NotRequired[]``.