From 74b07ca545edaf175756a119294da788e8b0df00 Mon Sep 17 00:00:00 2001 From: Tal Einat <532281+taleinat@users.noreply.github.com> Date: Tue, 6 Aug 2024 15:31:33 +0300 Subject: [PATCH] PEP 661: Small updates (#3897) * Suggest using e.g. `Literal[MISSING]` * Minor wording improvements --- peps/pep-0661.rst | 33 ++++++++------------------------- 1 file changed, 8 insertions(+), 25 deletions(-) diff --git a/peps/pep-0661.rst b/peps/pep-0661.rst index 4b6fd54be..1d9e00917 100644 --- a/peps/pep-0661.rst +++ b/peps/pep-0661.rst @@ -79,7 +79,7 @@ In the ensuing discussion, Victor Stinner supplied a list of currently used sentinel values in the Python standard library [2]_. This showed that the need for sentinels is fairly common, that there are various implementation methods used even within the stdlib, and that many of these suffer from at -least one of the three aforementioned drawbacks. +least one of the three above drawbacks. The discussion did not lead to any clear consensus on whether a standard implementation method is needed or desirable, whether the drawbacks mentioned @@ -160,7 +160,7 @@ operator, as is recommended for ``None``. Equality checks using ``==`` will also work as expected, returning ``True`` only when the object is compared with itself. Identity checks such as ``if value is MISSING:`` should usually be used rather than boolean checks such as ``if value:`` or ``if not value:``. -Sentinel instances are truthy by default. +Sentinel instances are truthy by default, unlike ``None``. The names of sentinels are unique within each module. When calling ``Sentinel()`` in a module where a sentinel with that name was already @@ -170,9 +170,10 @@ 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 ``Sentinel``. For example:: +Type annotations for sentinel values should use ``Literal[]``. +For example:: - def foo(value: int | Sentinel = MISSING) -> int: + def foo(value: int | Literal[MISSING] = MISSING) -> int: ... The ``module_name`` optional argument should normally not need to be supplied, @@ -337,27 +338,6 @@ idiom were unpopular, with the highest-voted option being voted for by only 25% of the voters. -Specific type signatures for each sentinel value ------------------------------------------------- - -For a long time, the author of this PEP strove to have type signatures for -such sentinels that were specific to each value. A leading proposal -(supported by Guido and others) was to expand the use of ``Literal``, e.g. -``Literal[MISSING]``. After much thought and discussion, especially on the -typing-sig mailing list [8]_, it seems that all such solutions would require -special-casing and/or added complexity in the implementations of static type -checkers, while also constraining the implementation of sentinels. - -Therefore, this PEP no longer proposes such signatures. Instead, this PEP -suggests using ``Sentinel`` as the type signature for sentinel values. - -It is somewhat unfortunate that static type checkers will sometimes not be -able to deduce more specific types due to this, such as inside a conditional -block like ``if value is not MISSING: ...``. However, this is a minor issue -in practice, as type checkers can be easily made to understand these cases -using ``typing.cast()``. - - Additional Notes ================ @@ -379,6 +359,9 @@ Additional Notes identical. If distinct sentinel objects are needed, make sure to use distinct names. +* There was a discussion on the typing-sig mailing list [8]_ about the typing + for these sentinels, where different options were discussed. + References ==========