|
| 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