Skip to content

Commit 68c2d4e

Browse files
koxudaxidpgeorge
authored andcommitted
docs/library: Document string.templatelib module.
This documents all of the available functionality in the new `string.templatelib` module, which is associated with template strings. Signed-off-by: Koudai Aono <koxudaxi@gmail.com> Signed-off-by: Damien George <damien@micropython.org>
1 parent bdef10a commit 68c2d4e

2 files changed

Lines changed: 231 additions & 0 deletions

File tree

docs/library/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ library.
7878
select.rst
7979
socket.rst
8080
ssl.rst
81+
string.templatelib.rst
8182
struct.rst
8283
sys.rst
8384
time.rst
Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
:mod:`string.templatelib` -- Template String Support
2+
====================================================
3+
4+
.. module:: string.templatelib
5+
:synopsis: PEP 750 template string support
6+
7+
This module provides support for template strings (t-strings) as defined in
8+
`PEP 750 <https://peps.python.org/pep-0750/>`_. Template strings are created
9+
using the ``t`` prefix and provide access to both the literal string parts and
10+
interpolated values before they are combined.
11+
12+
**Availability:** template strings require ``MICROPY_PY_TSTRINGS`` to be enabled
13+
at compile time. They are enabled by default at the full feature level, which
14+
includes the alif, mimxrt and samd (SAMD51 only) ports, the unix coverage variant
15+
and the webassembly pyscript variant.
16+
17+
Classes
18+
-------
19+
20+
.. class:: Template(*args)
21+
22+
Represents a template string. Template objects are typically created by
23+
t-string syntax (``t"..."``) but can also be constructed directly using
24+
the constructor.
25+
26+
.. attribute:: strings
27+
28+
A tuple of string literals that appear between interpolations.
29+
30+
.. attribute:: interpolations
31+
32+
A tuple of :class:`Interpolation` objects representing the interpolated
33+
expressions.
34+
35+
.. attribute:: values
36+
37+
A read-only property that returns a tuple containing the ``value``
38+
attribute from each interpolation in the template.
39+
40+
.. method:: __iter__()
41+
42+
Iterate over the template contents, yielding string parts and
43+
:class:`Interpolation` objects in the order they appear. Empty strings
44+
are omitted.
45+
46+
.. method:: __add__(other)
47+
48+
Concatenate two templates. Returns a new :class:`Template` combining
49+
the strings and interpolations from both templates.
50+
51+
:raises TypeError: if *other* is not a :class:`Template`
52+
53+
Template concatenation with ``str`` is prohibited to avoid ambiguity
54+
about whether the string should be treated as a literal or interpolation::
55+
56+
t1 = t"Hello "
57+
t2 = t"World"
58+
result = t1 + t2 # Valid
59+
60+
# TypeError: cannot concatenate str to Template
61+
result = t1 + "World"
62+
63+
.. class:: Interpolation(value, expression='', conversion=None, format_spec='')
64+
65+
Represents an interpolated expression within a template string. All
66+
arguments can be passed as keyword arguments.
67+
68+
.. attribute:: value
69+
70+
The evaluated value of the interpolated expression.
71+
72+
.. attribute:: expression
73+
74+
The string representation of the expression as it appeared in the
75+
template string.
76+
77+
.. attribute:: conversion
78+
79+
The conversion specifier (``'s'`` or ``'r'``) if present, otherwise ``None``.
80+
Note that MicroPython does not support the ``'a'`` conversion.
81+
82+
.. attribute:: format_spec
83+
84+
The format specification string if present, otherwise an empty string.
85+
86+
Template String Syntax
87+
----------------------
88+
89+
Template strings use the same syntax as f-strings but with a ``t`` prefix::
90+
91+
name = "World"
92+
template = t"Hello {name}!"
93+
94+
# Access template components
95+
print(template.strings) # ('Hello ', '!')
96+
print(template.values) # ('World',)
97+
print(template.interpolations[0].expression) # 'name'
98+
99+
Conversion Specifiers
100+
~~~~~~~~~~~~~~~~~~~~~
101+
102+
Template strings store conversion specifiers as metadata. Unlike f-strings,
103+
the conversion is not applied automatically::
104+
105+
value = "test"
106+
t = t"{value!r}"
107+
# t.interpolations[0].value == "test" (not repr(value))
108+
# t.interpolations[0].conversion == "r"
109+
110+
Processing code must explicitly apply conversions when needed.
111+
112+
Format Specifications
113+
~~~~~~~~~~~~~~~~~~~~~
114+
115+
Format specifications are stored as metadata in the ``Interpolation`` object.
116+
Unlike f-strings, formatting is not applied automatically::
117+
118+
pi = 3.14159
119+
t = t"{pi:.2f}"
120+
# t.interpolations[0].value == 3.14159 (not formatted)
121+
# t.interpolations[0].format_spec == ".2f"
122+
123+
Per PEP 750, processing code is not required to use format specifications, but
124+
when present they should be respected and match f-string behavior where possible.
125+
126+
Debug Format
127+
~~~~~~~~~~~~
128+
129+
The debug format ``{expr=}`` is supported::
130+
131+
x = 42
132+
t = t"{x=}"
133+
# t.strings == ("x=", "")
134+
# t.interpolations[0].expression == "x"
135+
# t.interpolations[0].conversion == "r"
136+
137+
.. admonition:: Important
138+
:class: attention
139+
140+
As per PEP 750, unlike f-strings, template strings do not automatically
141+
apply conversions or format specifications. This is by design to allow
142+
processing code to control how these are handled. Processing code must
143+
explicitly handle these attributes.
144+
145+
MicroPython does not provide the ``format()`` built-in function. Use
146+
string formatting methods like ``str.format()`` instead.
147+
148+
Example Usage
149+
-------------
150+
151+
Basic processing without format support::
152+
153+
def simple_process(template):
154+
"""Simple template processing"""
155+
parts = []
156+
for item in template:
157+
if isinstance(item, str):
158+
parts.append(item)
159+
else:
160+
parts.append(str(item.value))
161+
return "".join(parts)
162+
163+
Processing template with format support::
164+
165+
from string.templatelib import Template, Interpolation
166+
167+
def convert(value, conversion):
168+
"""Apply conversion specifier to value"""
169+
if conversion == "r":
170+
return repr(value)
171+
elif conversion == "s":
172+
return str(value)
173+
return value
174+
175+
def process_template(template):
176+
"""Process template with conversion and format support"""
177+
result = []
178+
for part in template:
179+
if isinstance(part, str):
180+
result.append(part)
181+
else: # Interpolation
182+
value = convert(part.value, part.conversion)
183+
if part.format_spec:
184+
# Apply format specification using str.format
185+
value = ("{:" + part.format_spec + "}").format(value)
186+
else:
187+
value = str(value)
188+
result.append(value)
189+
return "".join(result)
190+
191+
pi = 3.14159
192+
name = "Alice"
193+
t = t"{name!r}: {pi:.2f}"
194+
print(process_template(t))
195+
# Output: "'Alice': 3.14"
196+
197+
# Other format specifications work too
198+
value = 42
199+
print(process_template(t"{value:>10}")) # " 42"
200+
print(process_template(t"{value:04d}")) # "0042"
201+
202+
HTML escaping example::
203+
204+
def html_escape(value):
205+
"""Escape HTML special characters"""
206+
if not isinstance(value, str):
207+
value = str(value)
208+
return value.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;")
209+
210+
def safe_html(template):
211+
"""Convert template to HTML-safe string"""
212+
result = []
213+
for part in template:
214+
if isinstance(part, str):
215+
result.append(part)
216+
else:
217+
result.append(html_escape(part.value))
218+
return "".join(result)
219+
220+
user_input = "<script>alert('xss')</script>"
221+
t = t"User said: {user_input}"
222+
print(safe_html(t))
223+
# Output: "User said: &lt;script&gt;alert('xss')&lt;/script&gt;"
224+
225+
See Also
226+
--------
227+
228+
* `PEP 750 <https://peps.python.org/pep-0750/>`_ - Template Strings specification
229+
* :ref:`python:formatstrings` - Format string syntax
230+
* `Formatted string literals <https://docs.python.org/3/reference/lexical_analysis.html#f-strings>`_ - f-strings in Python

0 commit comments

Comments
 (0)