Skip to content

Commit 13aeb6a

Browse files
committed
Add template_strings.py lesson
1 parent 1f53055 commit 13aeb6a

1 file changed

Lines changed: 60 additions & 0 deletions

File tree

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
"""
2+
Template strings (t-strings) introduced in Python 3.14 (PEP 750).
3+
4+
T-strings look like f-strings but prefixed with 't' or 'T'. Instead of
5+
immediately evaluating to a string, they evaluate to a Template object from
6+
the string.templatelib module. This allows for deferred evaluation and
7+
custom processing of the template parts and interpolations.
8+
"""
9+
import string.templatelib
10+
11+
12+
def process_template(template):
13+
"""Simple processor to demonstrate how Template objects work."""
14+
# A Template object has 'strings' (tuple of static parts)
15+
# and 'interpolations' (tuple of evaluated expression results)
16+
# The number of strings is always len(interpolations) + 1
17+
result = []
18+
for i, s in enumerate(template.strings):
19+
result.append(s)
20+
if i < len(template.interpolations):
21+
# Each item in interpolations is an object with a 'value' attribute
22+
result.append(str(template.interpolations[i].value))
23+
return "".join(result)
24+
25+
26+
def main():
27+
name = "World"
28+
year = 2026
29+
30+
# 1. Basic t-string creation
31+
# It evaluates to a string.templatelib.Template object
32+
tpl = t"Hello {name}, welcome to {year}!"
33+
34+
assert isinstance(tpl, string.templatelib.Template)
35+
36+
# 2. Inspecting the template parts
37+
# Static parts of the string
38+
assert tpl.strings == ("Hello ", ", welcome to ", "!")
39+
40+
# Values of the expressions
41+
assert tpl.interpolations[0].value == "World"
42+
assert tpl.interpolations[1].value == 2026
43+
44+
# 3. Processing the template
45+
# We can join them together manually or with a processor
46+
processed = process_template(tpl)
47+
assert processed == "Hello World, welcome to 2026!"
48+
49+
# 4. T-strings are great for safe processing (e.g. SQL, HTML)
50+
# because they keep the structure separate from the data
51+
user_input = "'; DROP TABLE users; --"
52+
query_template = t"SELECT * FROM users WHERE name = {user_input}"
53+
54+
# In a real scenario, a processor would escape the values in query_template.interpolations
55+
assert query_template.strings == ("SELECT * FROM users WHERE name = ", "")
56+
assert query_template.interpolations[0].value == user_input
57+
58+
59+
if __name__ == "__main__":
60+
main()

0 commit comments

Comments
 (0)