Skip to content

GH-132661: Add string.templatelib.convert() #135217

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Doc/library/string.rst
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,8 @@ Some simple format string examples::
"Weight in tons {0.weight}" # 'weight' attribute of first positional arg
"Units destroyed: {players[0]}" # First element of keyword argument 'players'.

.. _formatstrings-conversion:

The *conversion* field causes a type coercion before formatting. Normally, the
job of formatting a value is done by the :meth:`~object.__format__` method of the value
itself. However, in some cases it is desirable to force a type to be formatted
Expand Down
46 changes: 46 additions & 0 deletions Doc/library/string.templatelib.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
:mod:`!string.templatelib` --- Support for template string literals
===================================================================

.. module:: string.templatelib
:synopsis: Support for template string literals.

**Source code:** :source:`Lib/string/templatelib.py`

--------------

.. versionadded:: 3.14

.. seealso::

:pep:`750` -- Template Strings

Types
-----

.. class:: Template

.. class:: Interpolation

Helper functions
----------------

.. function:: convert(obj, /, conversion)

Applies formatted string literal :ref:`conversion <formatstrings-conversion>`
semantics to the given object *obj*.
This is frequently useful for custom template string processing logic.

Three conversion flags are currently supported:

* ``'!s'`` which calls :func:`str` on the value,
* ``'!r'`` which calls :func:`repr`, and
* ``'!a'`` which calls :func:`ascii`.

If the conversion flag is ``None``, *obj* is returned unchanged.

.. _template-strings:

Template String Syntax
----------------------

Check warning on line 44 in Doc/library/string.templatelib.rst

View workflow job for this annotation

GitHub Actions / Docs / Docs

duplicate label template-strings, other instance in /home/runner/work/cpython/cpython/Doc/library/string.rst

.. TODO: Add section similar to :ref:`formatstrings`.
1 change: 1 addition & 0 deletions Doc/library/text.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Python's built-in string type in :ref:`textseq`.
.. toctree::

string.rst
string.templatelib.rst
re.rst
difflib.rst
textwrap.rst
Expand Down
17 changes: 12 additions & 5 deletions Lib/string/templatelib.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
"""Support for template string literals (t-strings)."""

__all__ = [
"Interpolation",
"Template",
]

t = t"{0}"
Template = type(t)
Interpolation = type(t.interpolations[0])
del t

def convert(obj, /, conversion):
"""Implements formatted string literals conversion semantics."""
if conversion is None:
return obj
if conversion == 'r':
return repr(obj)
if conversion == 's':
return str(obj)
if conversion == 'a':
return ascii(obj)
raise ValueError(f'invalid conversion specifier: {conversion!r}')

def _template_unpickle(*args):
import itertools

Expand Down
20 changes: 19 additions & 1 deletion Lib/test/test_string/test_templatelib.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import pickle
import unittest
from collections.abc import Iterator, Iterable
from string.templatelib import Template, Interpolation
from string.templatelib import Template, Interpolation, convert

from test.test_string._support import TStringBaseCase, fstring

Expand Down Expand Up @@ -156,5 +156,23 @@ def test_exhausted(self):
self.assertRaises(StopIteration, next, template_iter)


class TestFunctions(unittest.TestCase):
def test_convert(self):
for obj in ('Café', None, 3.14, b'bytes'):
with self.subTest(f'{obj=}'):
self.assertEqual(convert(obj, None), obj)
self.assertEqual(convert(obj, 's'), str(obj))
self.assertEqual(convert(obj, 'r'), repr(obj))
self.assertEqual(convert(obj, 'a'), ascii(obj))

# Invalid conversion specifier
with self.assertRaises(ValueError):
convert(obj, 'z')
with self.assertRaises(ValueError):
convert(obj, 1)
with self.assertRaises(ValueError):
convert(obj, object())


if __name__ == '__main__':
unittest.main()
Loading
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy