PEP 589: Small updates based on feedback from @gvanrossum (#1060)
These are the updates I promised in https://github.com/python/peps/pull/991.
This commit is contained in:
parent
9d2abd5db3
commit
92c6ff0d9b
68
pep-0589.rst
68
pep-0589.rst
|
@ -372,9 +372,9 @@ Discussion:
|
|||
f(b) # Type check error: 'B' not compatible with 'A'
|
||||
b['x'] + 1 # Runtime error: None + 1
|
||||
|
||||
* A TypedDict type with required keys is not consistent with a
|
||||
TypedDict type with non-required keys, since the latter allows keys
|
||||
to be deleted. Example where this is relevant::
|
||||
* A TypedDict type with a required key is not consistent with a
|
||||
TypedDict type where the same key is a non-required key, since the
|
||||
latter allows keys to be deleted. Example where this is relevant::
|
||||
|
||||
class A(TypedDict, total=False):
|
||||
x: int
|
||||
|
@ -479,8 +479,9 @@ the most important type safety violations to prevent:
|
|||
3. A key that is not defined in the TypedDict type is added.
|
||||
|
||||
A key that is not a literal should generally be rejected, since its
|
||||
value is unknown during type checking, and thus can cause some of
|
||||
the above violations.
|
||||
value is unknown during type checking, and thus can cause some of the
|
||||
above violations. (`Use of Final Values and Literal Types`_
|
||||
generalizes this to cover final names and literal types.)
|
||||
|
||||
The use of a key that is not known to exist should be reported as an
|
||||
error, even if this wouldn't necessarily generate a runtime type
|
||||
|
@ -503,9 +504,15 @@ Type checkers should reject the following operations on TypedDict
|
|||
objects as unsafe, even though they are valid for normal dictionaries:
|
||||
|
||||
* Operations with arbitrary ``str`` keys (instead of string literals
|
||||
or other expressions with known string values) should be rejected.
|
||||
This involves both destructive operations such as setting an item
|
||||
and read-only operations such as subscription expressions.
|
||||
or other expressions with known string values) should generally be
|
||||
rejected. This involves both destructive operations such as setting
|
||||
an item and read-only operations such as subscription expressions.
|
||||
As an exception to the above rule, ``d.get(e)`` and ``e in d``
|
||||
should be allowed for TypedDict objects, for an arbitrary expression
|
||||
``e`` with type ``str``. The motivation is that these are safe and
|
||||
can be useful for introspecting TypedDict objects. The static type
|
||||
of ``d.get(e)`` should be ``object`` if the string value of ``e``
|
||||
cannot be determined statically.
|
||||
|
||||
* ``clear()`` is not safe since it could remove required keys, some of
|
||||
which may not be directly visible because of structural
|
||||
|
@ -527,6 +534,33 @@ In some cases potentially unsafe operations may be accepted if the
|
|||
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 [#PEP-591]_) with
|
||||
string values to be used instead of string literals in operations on
|
||||
TypedDict objects. For example, this is valid::
|
||||
|
||||
YEAR: Final = 'year'
|
||||
|
||||
m: Movie = {'name': 'Alien', 'year': 1979}
|
||||
years_since_epoch = m[YEAR] - 1970
|
||||
|
||||
Similarly, an expression with a suitable literal type
|
||||
(PEP 586 [#PEP-586]_) can be used instead of a literal value::
|
||||
|
||||
def get_value(movie: Movie,
|
||||
key: Literal['year', 'name']) -> Union[int, str]:
|
||||
return movie[key]
|
||||
|
||||
Type checkers are only expected to support actual string literals, not
|
||||
final names or literal types, for specifying keys in a TypedDict type
|
||||
definition. Also, only a boolean literal can be used to specify
|
||||
totality in a TypedDict definition. The motivation for this is to
|
||||
make type declarations self-contained, and to simplify the
|
||||
implementation of type checkers.
|
||||
|
||||
|
||||
Backwards Compatibility
|
||||
=======================
|
||||
|
||||
|
@ -544,7 +578,9 @@ Reference Implementation
|
|||
|
||||
The mypy [#mypy]_ type checker supports TypedDict types. A reference
|
||||
implementation of the runtime component is provided in the
|
||||
``mypy_extensions`` [#mypy_extensions]_ module.
|
||||
``typing_extensions`` [#typing_extensions]_ module. The original
|
||||
implementation was in the ``mypy_extensions`` [#mypy_extensions]_
|
||||
module.
|
||||
|
||||
|
||||
Rejected Alternatives
|
||||
|
@ -576,7 +612,7 @@ this proposal:
|
|||
|
||||
* TypedDict types can't be used in ``isinstance()`` or ``issubclass()``
|
||||
checks. The reasoning is similar to why runtime type checks aren't
|
||||
supported in general.
|
||||
supported in general with many type hints.
|
||||
|
||||
These features were left out from this PEP, but they are potential
|
||||
extensions to be added in the future:
|
||||
|
@ -588,7 +624,8 @@ extensions to be added in the future:
|
|||
dictionary type.
|
||||
|
||||
* There is no way to individually specify whether each key is required
|
||||
or not. No proposed syntax was clear enough.
|
||||
or not. No proposed syntax was clear enough, and we expect that
|
||||
there is limited need for this.
|
||||
|
||||
* TypedDict can't be used for specifying the type of a ``**kwargs``
|
||||
argument. This would allow restricting the allowed keyword
|
||||
|
@ -624,8 +661,17 @@ References
|
|||
.. [#PEP-483] PEP 483, The Theory of Type Hints, van Rossum, Levkivskyi
|
||||
(http://www.python.org/dev/peps/pep-0483)
|
||||
|
||||
.. [#PEP-591] PEP 591, Adding a final qualifier to typing, Sullivan,
|
||||
Levkivskyi (http://www.python.org/dev/peps/pep-0591)
|
||||
|
||||
.. [#PEP-586] PEP 586, Literal Types, Lee, Levkivskyi, Lehtosalo
|
||||
(http://www.python.org/dev/peps/pep-0586)
|
||||
|
||||
.. [#mypy] http://www.mypy-lang.org/
|
||||
|
||||
.. [#typing_extensions]
|
||||
https://github.com/python/typing/tree/master/typing_extensions
|
||||
|
||||
.. [#mypy_extensions] https://github.com/python/mypy_extensions
|
||||
|
||||
.. [#typing_inspect] https://github.com/ilevkivskyi/typing_inspect
|
||||
|
|
Loading…
Reference in New Issue