Skip to content

Commit 7902b4e

Browse files
authored
Merge pull request #671 from realpython/python-t-strings
Sample code for the article on t-strings
2 parents e973327 + ce4582d commit 7902b4e

File tree

6 files changed

+134
-0
lines changed

6 files changed

+134
-0
lines changed

python-t-strings/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Python 3.14 Preview: Template Strings (T-Strings)
2+
3+
This folder provides the code examples for the Real Python tutorial [Python 3.14 Preview: Template Strings (T-Strings)](https://realpython.com/python-t-string/).

python-t-strings/asynchronous.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import asyncio
2+
3+
4+
async def get_name():
5+
# Simulate an asynchronous operation
6+
await asyncio.sleep(1)
7+
return "Pythonista"
8+
9+
10+
async def greeting_template():
11+
"Uncomment in Python 3.14+"
12+
# return t"Hello, {await get_name()}!"
13+
14+
15+
async def main():
16+
greeting = await greeting_template()
17+
print(greeting)
18+
19+
20+
asyncio.run(main())
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import json
2+
import logging
3+
from string.templatelib import Template
4+
5+
logging.basicConfig(level=logging.INFO, format="%(message)s")
6+
7+
8+
class TemplateMessage:
9+
def __init__(self, template):
10+
if not isinstance(template, Template):
11+
raise TypeError("t-string expected")
12+
self.template = template
13+
14+
@property
15+
def message(self):
16+
parts = []
17+
for item in self.template:
18+
if isinstance(item, str):
19+
parts.append(item)
20+
else:
21+
parts.append(str(item.value))
22+
return "".join(parts)
23+
24+
@property
25+
def values_dict(self):
26+
values = {}
27+
for item in self.template:
28+
if not isinstance(item, str):
29+
values[item.expression] = item.value
30+
return values
31+
32+
def __str__(self):
33+
return f"{self.message} >>> {json.dumps(self.values_dict)}"
34+
35+
36+
# Uncomment in Python 3.14+
37+
# action, amount, item = "refund", 7, "keyboard"
38+
# msg_template = TemplateMessage(t"Process {action}: {amount:.2f} {item}")
39+
# logging.info(msg_template)

python-t-strings/scape_html.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import html
2+
from string.templatelib import Template
3+
4+
5+
def generate_safe_html(template):
6+
if not isinstance(template, Template):
7+
raise TypeError("t-string expected")
8+
parts = []
9+
for item in template:
10+
if isinstance(item, str):
11+
parts.append(item)
12+
else:
13+
parts.append(html.escape(item.value))
14+
return "".join(parts)
15+
16+
17+
# Uncomment in Python 3.14+
18+
# username = "<script>alert('Hacked!')</script>"
19+
# template = t"<p>Hello, {username}!</p>"
20+
21+
# safe_html = render_safe_html(template)
22+
# print(safe_html)

python-t-strings/sql.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
from string.templatelib import Template
2+
3+
4+
def sanitized_sql(template):
5+
if not isinstance(template, Template):
6+
raise TypeError("t-string expected")
7+
parts = []
8+
params = []
9+
10+
for item in template:
11+
if isinstance(item, str):
12+
parts.append(item)
13+
else:
14+
parts.append("?")
15+
params.append(item.value)
16+
17+
query = "".join(parts)
18+
return query, tuple(params)
19+
20+
21+
# Uncomment in Python 3.14+
22+
# username = "john'); DROP TABLE students;--"
23+
# template = t"SELECT * FROM students WHERE name = {username}"
24+
# query, params = sanitized_sql(template)
25+
# print("Sanitized SQL Query:", query)
26+
27+
# print("Parameters:", params)

python-t-strings/to_strings.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
def to_string(template):
2+
def convert(value, conversion):
3+
func = {"a": ascii, "r": repr, "s": str}.get(conversion, lambda x: x)
4+
return func(value)
5+
6+
parts = []
7+
for item in template:
8+
if isinstance(item, str):
9+
parts.append(item)
10+
else:
11+
value = format(
12+
convert(item.value, item.conversion), item.format_spec
13+
)
14+
parts.append(value)
15+
return "".join(parts)
16+
17+
18+
# Uncomment in Python 3.14+
19+
# price = 234.8765
20+
# print(to_string(t"The price is ${price:.2f}"))
21+
22+
# header = "Report"
23+
# print(to_string(t"{header:=^20}"))

0 commit comments

Comments
 (0)