Skip to content

Commit

Permalink
Spec: Replace various direct references to PEPs (#1694)
Browse files Browse the repository at this point in the history
  • Loading branch information
JelleZijlstra authored Apr 7, 2024
1 parent ea4e9a3 commit 685f81a
Show file tree
Hide file tree
Showing 8 changed files with 38 additions and 43 deletions.
4 changes: 4 additions & 0 deletions docs/spec/annotations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down Expand Up @@ -222,6 +224,8 @@ types cannot be specified::
else:
return asyncio.Future(...)

.. _`annotating-methods`:

Annotating instance and class methods
-------------------------------------

Expand Down
4 changes: 3 additions & 1 deletion docs/spec/callables.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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``
-------------------------------------

Expand Down Expand Up @@ -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 <callable>`, such as variadic, overloaded, and complex generic
callbacks. They can be defined as protocols with a ``__call__`` member::

from typing import Protocol
Expand Down
8 changes: 4 additions & 4 deletions docs/spec/dataclasses.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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:

Expand Down Expand Up @@ -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 <https://docs.python.org/3/library/dataclasses.html#inheritance>`. This includes the effects of
overrides (redefining a field in a child class that has already been
defined in a parent class).

Expand Down
4 changes: 2 additions & 2 deletions docs/spec/directives.rst
Original file line number Diff line number Diff line change
Expand Up @@ -200,15 +200,15 @@ 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 <override>`
and the base class method it overrides is deprecated, the type checker should
produce a diagnostic.

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
^^^^^^^
Expand Down
7 changes: 4 additions & 3 deletions docs/spec/generics.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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 <annotating-args-kwargs>` 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.
Expand Down Expand Up @@ -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 <annotating-args-kwargs>`
of ``*args: int``, which accepts zero or
more values of type ``int``:

::
Expand Down
20 changes: 4 additions & 16 deletions docs/spec/literal.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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 <newtype>`.

Equivalence of two Literals
"""""""""""""""""""""""""""
Expand Down Expand Up @@ -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.

Expand Down Expand Up @@ -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::
Expand All @@ -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.

Expand Down
15 changes: 7 additions & 8 deletions docs/spec/protocol.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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 <https://docs.python.org/3/reference/datamodel.html#special-method-names>`_
in the subclass, see Python :py:ref:`data model <specialnames>`
for details.)

The attributes (variables and methods) of a protocol that are mandatory
Expand Down Expand Up @@ -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" <missing-annotations>`). Bodies of protocol methods are type checked.
An abstract method that should not be called via ``super()`` ought to raise
``NotImplementedError``. Example::

Expand All @@ -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
Expand All @@ -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 <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.

Expand Down Expand Up @@ -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 <forward-references>`. Recursive
protocols are useful for representing self-referential data structures
like trees in an abstract fashion::

Expand Down Expand Up @@ -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 <annotating-methods>`. For example::

C = TypeVar('C', bound='Copyable')
class Copyable(Protocol):
Expand Down
19 changes: 10 additions & 9 deletions docs/spec/typeddict.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
^^^^^^^^^^^^^^^^^^
Expand Down Expand Up @@ -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 <uppercase-final>` with
string values to be used instead of string literals in operations on
TypedDict objects. For example, this is valid::

Expand All @@ -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 <literal>`
can be used instead of a literal value::

def get_value(movie: Movie,
key: Literal['year', 'name']) -> int | str:
Expand Down Expand Up @@ -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 <typeddict-functional-syntax>`
for TypedDict also supports
``Required[]``, ``NotRequired[]``, and ``ReadOnly[]``:

Expand All @@ -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[]``.

Expand Down

0 comments on commit 685f81a

Please sign in to comment.