mirror of
https://github.com/micropython/micropython.git
synced 2026-03-10 10:50:17 +01:00
Some checks are pending
JavaScript code lint and formatting with Biome / eslint (push) Waiting to run
Check code formatting / code-formatting (push) Waiting to run
Check spelling with codespell / codespell (push) Waiting to run
Build docs / build (push) Waiting to run
Check examples / embedding (push) Waiting to run
Package mpremote / build (push) Waiting to run
.mpy file format and tools / test (push) Waiting to run
Build ports metadata / build (push) Waiting to run
alif port / build_alif (alif_ae3_build) (push) Waiting to run
cc3200 port / build (push) Waiting to run
esp32 port / build_idf (esp32_build_c2_c5_c6) (push) Waiting to run
esp32 port / build_idf (esp32_build_cmod_spiram_s2) (push) Waiting to run
esp32 port / build_idf (esp32_build_p4) (push) Waiting to run
esp32 port / build_idf (esp32_build_s3_c3) (push) Waiting to run
esp8266 port / build (push) Waiting to run
mimxrt port / build (push) Waiting to run
nrf port / build (push) Waiting to run
powerpc port / build (push) Waiting to run
qemu port / build_and_test_arm (bigendian) (push) Waiting to run
qemu port / build_and_test_arm (sabrelite) (push) Waiting to run
qemu port / build_and_test_arm (thumb_hardfp) (push) Waiting to run
qemu port / build_and_test_arm (thumb_softfp) (push) Waiting to run
qemu port / build_and_test_rv32 (push) Waiting to run
qemu port / build_and_test_rv64 (push) Waiting to run
renesas-ra port / build_renesas_ra_board (push) Waiting to run
rp2 port / build (push) Waiting to run
samd port / build (push) Waiting to run
stm32 port / build_stm32 (stm32_misc_build) (push) Waiting to run
stm32 port / build_stm32 (stm32_nucleo_build) (push) Waiting to run
stm32 port / build_stm32 (stm32_pyb_build) (push) Waiting to run
unix port / minimal (push) Waiting to run
unix port / reproducible (push) Waiting to run
unix port / standard (push) Waiting to run
unix port / standard_v2 (push) Waiting to run
unix port / coverage (push) Waiting to run
unix port / coverage_32bit (push) Waiting to run
unix port / nanbox (push) Waiting to run
unix port / longlong (push) Waiting to run
unix port / float (push) Waiting to run
unix port / gil_enabled (push) Waiting to run
unix port / stackless_clang (push) Waiting to run
unix port / float_clang (push) Waiting to run
unix port / settrace_stackless (push) Waiting to run
unix port / repr_b (push) Waiting to run
unix port / macos (push) Waiting to run
unix port / qemu_mips (push) Waiting to run
unix port / qemu_arm (push) Waiting to run
unix port / qemu_riscv64 (push) Waiting to run
unix port / sanitize_address (push) Waiting to run
unix port / sanitize_undefined (push) Waiting to run
webassembly port / build (push) Waiting to run
windows port / build-vs (Debug, true, x64, dev, 2017, [15, 16)) (push) Waiting to run
windows port / build-vs (Debug, true, x86, dev, 2017, [15, 16)) (push) Waiting to run
windows port / build-vs (Debug, x64, dev, 2022, [17, 18)) (push) Waiting to run
windows port / build-vs (Debug, x86, dev, 2022, [17, 18)) (push) Waiting to run
windows port / build-vs (Release, true, x64, dev, 2017, [15, 16)) (push) Waiting to run
windows port / build-vs (Release, true, x64, dev, 2019, [16, 17)) (push) Waiting to run
windows port / build-vs (Release, true, x64, standard, 2017, [15, 16)) (push) Waiting to run
windows port / build-vs (Release, true, x64, standard, 2019, [16, 17)) (push) Waiting to run
windows port / build-vs (Release, true, x86, dev, 2017, [15, 16)) (push) Waiting to run
windows port / build-vs (Release, true, x86, dev, 2019, [16, 17)) (push) Waiting to run
windows port / build-vs (Release, true, x86, standard, 2017, [15, 16)) (push) Waiting to run
windows port / build-vs (Release, true, x86, standard, 2019, [16, 17)) (push) Waiting to run
windows port / build-vs (Release, x64, dev, 2022, [17, 18)) (push) Waiting to run
windows port / build-vs (Release, x64, standard, 2022, [17, 18)) (push) Waiting to run
windows port / build-vs (Release, x86, dev, 2022, [17, 18)) (push) Waiting to run
windows port / build-vs (Release, x86, standard, 2022, [17, 18)) (push) Waiting to run
windows port / build-mingw (i686, mingw32, dev) (push) Waiting to run
windows port / build-mingw (i686, mingw32, standard) (push) Waiting to run
windows port / build-mingw (x86_64, mingw64, dev) (push) Waiting to run
windows port / build-mingw (x86_64, mingw64, standard) (push) Waiting to run
windows port / cross-build-on-linux (push) Waiting to run
zephyr port / build (push) Waiting to run
Python code lint and formatting with ruff / ruff (push) Waiting to run
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>
231 lines
7.2 KiB
ReStructuredText
231 lines
7.2 KiB
ReStructuredText
:mod:`string.templatelib` -- Template String Support
|
|
====================================================
|
|
|
|
.. module:: string.templatelib
|
|
:synopsis: PEP 750 template string support
|
|
|
|
This module provides support for template strings (t-strings) as defined in
|
|
`PEP 750 <https://peps.python.org/pep-0750/>`_. Template strings are created
|
|
using the ``t`` prefix and provide access to both the literal string parts and
|
|
interpolated values before they are combined.
|
|
|
|
**Availability:** template strings require ``MICROPY_PY_TSTRINGS`` to be enabled
|
|
at compile time. They are enabled by default at the full feature level, which
|
|
includes the alif, mimxrt and samd (SAMD51 only) ports, the unix coverage variant
|
|
and the webassembly pyscript variant.
|
|
|
|
Classes
|
|
-------
|
|
|
|
.. class:: Template(*args)
|
|
|
|
Represents a template string. Template objects are typically created by
|
|
t-string syntax (``t"..."``) but can also be constructed directly using
|
|
the constructor.
|
|
|
|
.. attribute:: strings
|
|
|
|
A tuple of string literals that appear between interpolations.
|
|
|
|
.. attribute:: interpolations
|
|
|
|
A tuple of :class:`Interpolation` objects representing the interpolated
|
|
expressions.
|
|
|
|
.. attribute:: values
|
|
|
|
A read-only property that returns a tuple containing the ``value``
|
|
attribute from each interpolation in the template.
|
|
|
|
.. method:: __iter__()
|
|
|
|
Iterate over the template contents, yielding string parts and
|
|
:class:`Interpolation` objects in the order they appear. Empty strings
|
|
are omitted.
|
|
|
|
.. method:: __add__(other)
|
|
|
|
Concatenate two templates. Returns a new :class:`Template` combining
|
|
the strings and interpolations from both templates.
|
|
|
|
:raises TypeError: if *other* is not a :class:`Template`
|
|
|
|
Template concatenation with ``str`` is prohibited to avoid ambiguity
|
|
about whether the string should be treated as a literal or interpolation::
|
|
|
|
t1 = t"Hello "
|
|
t2 = t"World"
|
|
result = t1 + t2 # Valid
|
|
|
|
# TypeError: cannot concatenate str to Template
|
|
result = t1 + "World"
|
|
|
|
.. class:: Interpolation(value, expression='', conversion=None, format_spec='')
|
|
|
|
Represents an interpolated expression within a template string. All
|
|
arguments can be passed as keyword arguments.
|
|
|
|
.. attribute:: value
|
|
|
|
The evaluated value of the interpolated expression.
|
|
|
|
.. attribute:: expression
|
|
|
|
The string representation of the expression as it appeared in the
|
|
template string.
|
|
|
|
.. attribute:: conversion
|
|
|
|
The conversion specifier (``'s'`` or ``'r'``) if present, otherwise ``None``.
|
|
Note that MicroPython does not support the ``'a'`` conversion.
|
|
|
|
.. attribute:: format_spec
|
|
|
|
The format specification string if present, otherwise an empty string.
|
|
|
|
Template String Syntax
|
|
----------------------
|
|
|
|
Template strings use the same syntax as f-strings but with a ``t`` prefix::
|
|
|
|
name = "World"
|
|
template = t"Hello {name}!"
|
|
|
|
# Access template components
|
|
print(template.strings) # ('Hello ', '!')
|
|
print(template.values) # ('World',)
|
|
print(template.interpolations[0].expression) # 'name'
|
|
|
|
Conversion Specifiers
|
|
~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Template strings store conversion specifiers as metadata. Unlike f-strings,
|
|
the conversion is not applied automatically::
|
|
|
|
value = "test"
|
|
t = t"{value!r}"
|
|
# t.interpolations[0].value == "test" (not repr(value))
|
|
# t.interpolations[0].conversion == "r"
|
|
|
|
Processing code must explicitly apply conversions when needed.
|
|
|
|
Format Specifications
|
|
~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Format specifications are stored as metadata in the ``Interpolation`` object.
|
|
Unlike f-strings, formatting is not applied automatically::
|
|
|
|
pi = 3.14159
|
|
t = t"{pi:.2f}"
|
|
# t.interpolations[0].value == 3.14159 (not formatted)
|
|
# t.interpolations[0].format_spec == ".2f"
|
|
|
|
Per PEP 750, processing code is not required to use format specifications, but
|
|
when present they should be respected and match f-string behavior where possible.
|
|
|
|
Debug Format
|
|
~~~~~~~~~~~~
|
|
|
|
The debug format ``{expr=}`` is supported::
|
|
|
|
x = 42
|
|
t = t"{x=}"
|
|
# t.strings == ("x=", "")
|
|
# t.interpolations[0].expression == "x"
|
|
# t.interpolations[0].conversion == "r"
|
|
|
|
.. admonition:: Important
|
|
:class: attention
|
|
|
|
As per PEP 750, unlike f-strings, template strings do not automatically
|
|
apply conversions or format specifications. This is by design to allow
|
|
processing code to control how these are handled. Processing code must
|
|
explicitly handle these attributes.
|
|
|
|
MicroPython does not provide the ``format()`` built-in function. Use
|
|
string formatting methods like ``str.format()`` instead.
|
|
|
|
Example Usage
|
|
-------------
|
|
|
|
Basic processing without format support::
|
|
|
|
def simple_process(template):
|
|
"""Simple template processing"""
|
|
parts = []
|
|
for item in template:
|
|
if isinstance(item, str):
|
|
parts.append(item)
|
|
else:
|
|
parts.append(str(item.value))
|
|
return "".join(parts)
|
|
|
|
Processing template with format support::
|
|
|
|
from string.templatelib import Template, Interpolation
|
|
|
|
def convert(value, conversion):
|
|
"""Apply conversion specifier to value"""
|
|
if conversion == "r":
|
|
return repr(value)
|
|
elif conversion == "s":
|
|
return str(value)
|
|
return value
|
|
|
|
def process_template(template):
|
|
"""Process template with conversion and format support"""
|
|
result = []
|
|
for part in template:
|
|
if isinstance(part, str):
|
|
result.append(part)
|
|
else: # Interpolation
|
|
value = convert(part.value, part.conversion)
|
|
if part.format_spec:
|
|
# Apply format specification using str.format
|
|
value = ("{:" + part.format_spec + "}").format(value)
|
|
else:
|
|
value = str(value)
|
|
result.append(value)
|
|
return "".join(result)
|
|
|
|
pi = 3.14159
|
|
name = "Alice"
|
|
t = t"{name!r}: {pi:.2f}"
|
|
print(process_template(t))
|
|
# Output: "'Alice': 3.14"
|
|
|
|
# Other format specifications work too
|
|
value = 42
|
|
print(process_template(t"{value:>10}")) # " 42"
|
|
print(process_template(t"{value:04d}")) # "0042"
|
|
|
|
HTML escaping example::
|
|
|
|
def html_escape(value):
|
|
"""Escape HTML special characters"""
|
|
if not isinstance(value, str):
|
|
value = str(value)
|
|
return value.replace("&", "&").replace("<", "<").replace(">", ">")
|
|
|
|
def safe_html(template):
|
|
"""Convert template to HTML-safe string"""
|
|
result = []
|
|
for part in template:
|
|
if isinstance(part, str):
|
|
result.append(part)
|
|
else:
|
|
result.append(html_escape(part.value))
|
|
return "".join(result)
|
|
|
|
user_input = "<script>alert('xss')</script>"
|
|
t = t"User said: {user_input}"
|
|
print(safe_html(t))
|
|
# Output: "User said: <script>alert('xss')</script>"
|
|
|
|
See Also
|
|
--------
|
|
|
|
* `PEP 750 <https://peps.python.org/pep-0750/>`_ - Template Strings specification
|
|
* :ref:`python:formatstrings` - Format string syntax
|
|
* `Formatted string literals <https://docs.python.org/3/reference/lexical_analysis.html#f-strings>`_ - f-strings in Python
|