From 8ae21fff71bde7b95b352b01bdb8a9939738f1d2 Mon Sep 17 00:00:00 2001 From: Alyssa Coghlan Date: Sun, 20 Oct 2024 00:00:43 +1000 Subject: [PATCH 1/2] PEP 501: Withdraw in favour of PEP 750 (#4070) --- peps/pep-0501.rst | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/peps/pep-0501.rst b/peps/pep-0501.rst index 9eb16cbba10..0f875ea9b0c 100644 --- a/peps/pep-0501.rst +++ b/peps/pep-0501.rst @@ -2,17 +2,17 @@ PEP: 501 Title: General purpose template literal strings Author: Alyssa Coghlan , Nick Humrich Discussions-To: https://discuss.python.org/t/pep-501-reopen-general-purpose-string-template-literals/24625 -Status: Draft +Status: Withdrawn Type: Standards Track -Content-Type: text/x-rst Requires: 701 Created: 08-Aug-2015 Python-Version: 3.12 Post-History: `08-Aug-2015 `__, `05-Sep-2015 `__, `09-Mar-2023 `__, +Superseded-By: 750 -.. TODO: Start new PEP 501 d.p.o thread once these updates have been merged +.. superseded:: 750 Abstract ======== @@ -31,6 +31,34 @@ appropriate escaping and other string processing on inputs while retaining the usability and convenience of f-strings. +PEP Withdrawal +============== + +When :pep:`750` was first published as a "tagged strings" proposal +(allowing for arbitrary string prefixes), this PEP was kept open to +continue championing the simpler "template literal" approach that +used a single dedicated string prefix to produce instances of a new +"interpolation template" type. + +The `October 2024 updates `__ +to :pep:`750` agreed that template strings were a better fit for Python +than the broader tagged strings concept. + +All of the other concerns the authors of this PEP had with :pep:`750` +were also either addressed in those updates, or else left in a state +where they could reasonably be addressed in a future change proposal. + +Due to the clear improvements in the updated :pep:`750` proposal, +this PEP has been withdrawn in favour of :pep:`750`. + +.. important:: + + The remainder of this PEP still reflects the state of the tagged strings + proposal in August 2024. It has *not* been updated to reflect the + October 2024 changes to :pep:`750`, since the PEP withdrawal makes doing + so redundant. + + Relationship with other PEPs ============================ From 1c213ece4bcb5ffcb5b794d5491f4142e80f28cd Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Sat, 19 Oct 2024 07:29:26 -0700 Subject: [PATCH 2/2] 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> --- peps/pep-0661.rst | 51 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 45 insertions(+), 6 deletions(-) diff --git a/peps/pep-0661.rst b/peps/pep-0661.rst index 01628cb8f0c..021b96430df 100644 --- a/peps/pep-0661.rst +++ b/peps/pep-0661.rst @@ -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[]``. -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 `, 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 `. They +represent a :term:`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 =======================