PEP 661: Proposed typing specification changes (#4065)
This is an attempt to specify the behavior that I suggested on Discuss and that has been endorsed by the Typing Council. Co-authored-by: Tal Einat <532281+taleinat@users.noreply.github.com>
This commit is contained in:
parent
8ae21fff71
commit
1c213ece4b
|
@ -177,12 +177,6 @@ with the same name in different modules will be distinct from each other.
|
|||
Creating a copy of a sentinel object, such as by using ``copy.copy()`` or by
|
||||
pickling and unpickling, will return the same object.
|
||||
|
||||
Type annotations for sentinel values should use ``Literal[<sentinel_object>]``.
|
||||
For example::
|
||||
|
||||
def foo(value: int | Literal[MISSING] = MISSING) -> int:
|
||||
...
|
||||
|
||||
The ``module_name`` optional argument should normally not need to be supplied,
|
||||
as ``Sentinel()`` will usually be able to recognize the module in which it was
|
||||
called. ``module_name`` should be supplied only in unusual cases when this
|
||||
|
@ -197,6 +191,51 @@ add minimal complexity.
|
|||
|
||||
Ordering comparisons are undefined for sentinel objects.
|
||||
|
||||
Typing
|
||||
------
|
||||
|
||||
To make usage of sentinels clear and simple in typed Python code, we propose to
|
||||
amend the type system with a special case for sentinel objects.
|
||||
|
||||
Sentinel objects may be used in
|
||||
:term:`type expressions <typing:type expression>`, representing themselves.
|
||||
This is similar to how ``None`` is handled in the existing type system. For
|
||||
example::
|
||||
|
||||
from sentinels import Sentinel
|
||||
|
||||
MISSING = Sentinel('MISSING')
|
||||
|
||||
def foo(value: int | MISSING = MISSING) -> int:
|
||||
...
|
||||
|
||||
More formally, type checkers should recognize sentinel creations of the form
|
||||
``NAME = Sentinel('NAME')`` as creating a new sentinel object. If the name
|
||||
passed to the ``Sentinel`` constructor does not match the name the object is
|
||||
assigned to, type checkers should emit an error.
|
||||
|
||||
Sentinels defined using this syntax may be used in
|
||||
:term:`type expressions <typing:type expression>`. They
|
||||
represent a :term:`fully static type <typing:fully static type>` that has a
|
||||
single member, the sentinel object itself.
|
||||
|
||||
Type checkers should support narrowing union types involving sentinels
|
||||
using the ``is`` and ``is not`` operators::
|
||||
|
||||
from sentinels import Sentinel
|
||||
from typing import assert_type
|
||||
|
||||
MISSING = Sentinel('MISSING')
|
||||
|
||||
def foo(value: int | MISSING) -> None:
|
||||
if value is MISSING:
|
||||
assert_type(value, MISSING)
|
||||
else:
|
||||
assert_type(value, int)
|
||||
|
||||
To support usage in type expressions, the runtime implementation
|
||||
of the ``Sentinel`` class should have the ``__or__`` and ``__ror__``
|
||||
methods, returning :py:class:`typing.Union` objects.
|
||||
|
||||
Backwards Compatibility
|
||||
=======================
|
||||
|
|
Loading…
Reference in New Issue