From e660248bea6c067c7f4b930ff6e17f9c2242c193 Mon Sep 17 00:00:00 2001 From: Alyssa Coghlan Date: Fri, 13 Sep 2024 18:53:53 +1000 Subject: [PATCH] PEP 501: Minor editing fixes (#3946) Also fixes an incorrect comment about the impact a CPython operand precedence bug will have on the way template literals interact with regular strings. --- peps/pep-0501.rst | 47 ++++++++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 19 deletions(-) diff --git a/peps/pep-0501.rst b/peps/pep-0501.rst index 7bcc6162c..9eb16cbba 100644 --- a/peps/pep-0501.rst +++ b/peps/pep-0501.rst @@ -22,8 +22,9 @@ can be vulnerable to injection attacks when used to construct shell commands, SQL queries, HTML snippets and similar (for example, ``os.system(f"echo {message_from_user}")``). This PEP introduces template literal strings (or "t-strings"), -which have the same syntax and semantics but with rendering deferred -until :func:`format` or another template rendering function is called on them. +which have syntax and semantics that are similar to f-strings, +but with rendering deferred until :func:`format` or another +template rendering function is called on them. This will allow standard library calls, helper functions and third party tools to safety and intelligently perform appropriate escaping and other string processing on inputs @@ -49,7 +50,7 @@ inspired by the tagged strings proposal). This PEP does NOT propose an alternative to :pep:`292` for user interface internationalization use cases (but does note the potential for future syntactic -enhancements aimed at that use case that would benefit from the compiler-support +enhancements aimed at that use case that would benefit from the compiler-supported value interpolation machinery that this PEP and :pep:`750` introduce). @@ -85,7 +86,7 @@ help make it easier to write code that uses safer alternatives (such as To address that problem (and a number of other concerns), this PEP proposes the complementary introduction of "t-strings" (a mnemonic for "template literal strings"), where ``format(t"Message with {data}")`` would produce the same result as -``f"Message with {data}"``, but the interpolation template instance can instead be passed +``f"Message with {data}"``, but the template literal instance can instead be passed to other template rendering functions which process the contents of the template differently. @@ -150,8 +151,8 @@ Lazy field evaluation conversion specifier ------------------------------------------ In addition to the existing support for the ``a``, ``r``, and ``s`` conversion specifiers, -:meth:`str.format` and :meth:`str.format_map` will be updated to accept ``()`` as a -conversion specifier that means "call the interpolated value". +:meth:`str.format`, :meth:`str.format_map`, and :class:`string.Formatter` will be updated +to accept ``()`` as a conversion specifier that means "call the interpolated value". To support application of the standard conversion specifiers in custom template rendering functions, a new :func:`!operator.convert_field` function will be added. @@ -169,9 +170,12 @@ To allow additional field-specific directives to be passed to custom rendering f a way that still allows formatting of the template with the default renderer, the conversion specifier field will be allowed to contain a second ``!`` character. -:func:`!operator.convert_field` and :func:`format` (and hence the default template rendering -function) will ignore that character and any subsequent text in the conversion specifier -field. +:func:`!operator.convert_field` and :func:`format` (and hence the default +``TemplateLiteral.render`` template rendering method), will ignore that character and any +subsequent text in the conversion specifier field. + +:meth:`str.format`, :meth:`str.format_map`, and :class:`string.Formatter` will also be +updated to accept (and ignore) custom conversion specifiers. Template renderer for POSIX shell commands @@ -223,8 +227,13 @@ The key differences between f-strings and t-strings are: * unlike f-strings (where conversion specifiers are handled directly in the compiler), t-string conversion specifiers are handled at rendering time by the rendering function * the new ``!()`` conversion specifier indicates that the field expression is a callable - that should be called when using the default :func:`format` rendering function. This specifier - is specifically *not* being added to f-strings (since it is pointless there). + that should be called when using the default :func:`format` rendering function. This + specifier is specifically *not* being added to f-strings (since it is pointless there). +* a second ``!`` is allowed in t-string conversion specifiers (with any subsequent text + being ignored) as a way to allow custom template rendering functions to accept custom + conversion specifiers without breaking the default :func:`!TemplateLiteral.render` + rendering method. This feature is specifically *not* being added to f-strings (since + it is pointless there). * while f-string ``f"Message {here}"`` would be *semantically* equivalent to ``format(t"Message {here}")``, f-strings will continue to be supported directly in the compiler and hence avoid the runtime overhead of actually using the delayed rendering @@ -262,8 +271,8 @@ cosmetic than substantive. In particular: * this PEP proposes exact details for the proposed APIs of the concrete implementation types (including concatenation and repetition support, which are not part of the structural typing protocols) -* this PEP proposes changes to the existing :func:`format` builtin to make it usable directly as - template field renderer +* this PEP proposes changes to the existing :func:`format` builtin to make it usable + directly as a template field renderer The two PEPs also differ in *how* they make their case for delayed rendering support. This PEP focuses more on the concrete implementation concept of using template literals to allow @@ -316,7 +325,7 @@ entire combined literal forming the template literal. The template string is parsed into literals, expressions, format specifiers, and conversion specifiers as described for f-strings in :pep:`498` and :pep:`701`. The syntax for conversion specifiers is relaxed such that arbitrary strings are accepted (excluding those containing -``{``, ``}`` and ``:``) rather than being restricted to valid Python identifiers. +``{``, ``}`` or ``:``) rather than being restricted to valid Python identifiers. However, rather than being rendered directly into a formatted string, these components are instead organised into instances of new types with the @@ -493,9 +502,9 @@ following behaviour: def __radd__(self, other) -> TemplateLiteral|NotImplemented: if isinstance(other, str): - # Treat the given string as a new raw text segment. This will likely never - # run in practice due to https://github.com/python/cpython/issues/55686, - # but it at least makes the *intended* behaviour in this case clear. + # Treat the given string as a new raw text segment. This effectively + # has precedence over string concatenation in CPython due to + # https://github.com/python/cpython/issues/55686 combined_raw_text = other + self._raw combined_segments = (TemplateLiteralText(other),) + self._segments return TemplateLiteral(combined_raw_text, *combined_segments) @@ -731,7 +740,7 @@ Structural typing and duck typing --------------------------------- To allow custom renderers to accept alternative interpolation template implementations -(rather than being tightly coupled to the native interpolation template types), the +(rather than being tightly coupled to the native template literal types), the following structural protocols will be added to the ``typing`` module: .. code-block:: python @@ -1155,7 +1164,7 @@ fields in format specifiers). Defining repetition and concatenation semantics ----------------------------------------------- -This PEPs explicitly defines repetition and concatenation semantics for ``TemplateLiteral`` +This PEP explicitly defines repetition and concatenation semantics for ``TemplateLiteral`` and ``TemplateLiteralText``. While not strictly necessary, defining these is expected to make the types easier to work with in code that historically only supported regular strings.