Skip to content

Commit

Permalink
Merge branch 'main' into pep-667-exec-impact
Browse files Browse the repository at this point in the history
  • Loading branch information
ncoghlan authored Oct 19, 2024
2 parents 713ec6f + 1c213ec commit f875410
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 9 deletions.
34 changes: 31 additions & 3 deletions peps/pep-0501.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@ PEP: 501
Title: General purpose template literal strings
Author: Alyssa Coghlan <ncoghlan@gmail.com>, Nick Humrich <nick@humrich.us>
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 <https://mail.python.org/archives/list/python-dev@python.org/thread/EAZ3P2M3CDDIQFR764NF6FXQHWXYMKJF/>`__,
`05-Sep-2015 <https://mail.python.org/archives/list/python-dev@python.org/thread/ILVRPS6DTFZ7IHL5HONDBB6INVXTFOZ2/>`__,
`09-Mar-2023 <https://discuss.python.org/t/pep-501-reopen-general-purpose-string-template-literals/24625>`__,
Superseded-By: 750

.. TODO: Start new PEP 501 d.p.o thread once these updates have been merged
.. superseded:: 750

Abstract
========
Expand All @@ -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 <https://github.com/python/peps/pull/4062>`__
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
============================

Expand Down
51 changes: 45 additions & 6 deletions peps/pep-0661.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
=======================
Expand Down

0 comments on commit f875410

Please sign in to comment.