Skip to content

Commit ec99d3a

Browse files
committed
Sample code for the article on t-strings
1 parent 10cc2cc commit ec99d3a

File tree

10 files changed

+223
-0
lines changed

10 files changed

+223
-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: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
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+
return t"Hello, {await get_name()}!"
12+
13+
14+
async def main():
15+
greeting = await greeting_template()
16+
print(greeting)
17+
18+
19+
asyncio.run(main())

python-t-strings/emails.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
def fill_order_template(lang, name, order_id, date):
2+
templates = {
3+
"en": t"Thank you, {name}! Your order #{order_id} will arrive on {date}.",
4+
"es": t"Gracias, {name} Su orden No. {order_id} arribará el próximo {date}.",
5+
"fr": t"Merci, {name}! Votre commande n° {order_id} arrivera le {date}.",
6+
}
7+
return templates.get(lang, templates["en"])
8+
9+
10+
def generate_order_email(template):
11+
parts = []
12+
for item in template:
13+
if isinstance(item, str):
14+
parts.append(item)
15+
else:
16+
parts.append(str(item.value))
17+
return "".join(parts)
18+
19+
20+
template = fill_order_template("en", "Alice", 12345, "June 10")
21+
email = generate_order_email(template)
22+
print(email)

python-t-strings/i18n.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
name = input("Enter your name please: ")
2+
3+
translations = {
4+
"en": t"Hello, {name}! Welcome back!",
5+
"es": t"¡Hola, {name}! ¡Bienvenido de vuelta!",
6+
"fr": t"Bonjour, {name}! Bon retour!"
7+
}
8+
9+
10+
def get_localized_greeting(lang):
11+
template = translations.get(lang, translations["en"])
12+
parts = []
13+
for item in template:
14+
if isinstance(item, str):
15+
parts.append(item)
16+
else:
17+
parts.append(item.value)
18+
return "".join(parts)
19+
20+
21+
print(get_localized_greeting("en"))
22+
print(get_localized_greeting("es"))
23+
print(get_localized_greeting("fr"))
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import json
2+
import logging
3+
4+
logging.basicConfig(level=logging.INFO, format='%(message)s')
5+
6+
7+
class TemplateMessage:
8+
def __init__(self, template):
9+
self.template = template
10+
11+
@property
12+
def message(self):
13+
parts = []
14+
for item in self.template:
15+
if isinstance(item, str):
16+
parts.append(item)
17+
else:
18+
parts.append(str(item.value))
19+
return "".join(parts)
20+
21+
@property
22+
def values_dict(self):
23+
values = {}
24+
for item in self.template:
25+
if not isinstance(item, str):
26+
values[item.expression] = item.value
27+
return values
28+
29+
def __str__(self):
30+
return f"{self.message} >>> {json.dumps(self.values_dict)}"
31+
32+
33+
action, amount, item = "refund", 7, "keyboard"
34+
msg_template = TemplateMessage(t"Process {action}: {amount:.2f} {item}")
35+
logging.info(msg_template)

python-t-strings/scape_html.py

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

python-t-strings/sql.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
def sanitized_sql(template):
2+
parts = []
3+
params = []
4+
5+
for item in template:
6+
if isinstance(item, str):
7+
parts.append(item)
8+
else:
9+
parts.append("?")
10+
params.append(item.value)
11+
12+
query = "".join(parts)
13+
return query, tuple(params)
14+
15+
16+
template = t"SELECT * FROM students WHERE name = '{username}';"
17+
query, params = sanitized_sql(template)
18+
print("Sanitized SQL Query:", query)
19+
print("Parameters:", params)
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
def to_string(template):
2+
parts = []
3+
for part in template:
4+
if isinstance(part, str):
5+
parts.append(part)
6+
else:
7+
value = {
8+
"a": ascii,
9+
"r": repr,
10+
"s": str}.get(part.conversion, lambda _: part.conversion)(part.value)
11+
value = format(value, part.format_spec)
12+
parts.append(value)
13+
return "".join(parts)
14+
15+
16+
price = 234.8765
17+
print(to_string(t"The price is ${price:.2f}"))
18+
print(to_string(t"The price is ${price!s:.2f}"))

python-t-strings/to_stirngs.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
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(convert(item.value, item.conversion), item.format_spec)
12+
parts.append(value)
13+
return "".join(parts)
14+
15+
16+
price = 234.8765
17+
print(to_string(t"The price is ${price:.2f}"))
18+
19+
header = "Report"
20+
print(to_string(t"{header:=^20}"))

python-t-strings/traverse_items.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
from string.templatelib import Interpolation
2+
3+
name = "Pythonista"
4+
site = "realpython.com"
5+
template = t"Hello, {name}! Welcome to {site}!"
6+
7+
# for item in template:
8+
# print(item)
9+
10+
# for s in template.strings:
11+
# print(s)
12+
13+
for value in template.values:
14+
print(value)
15+
16+
debit = 300.4344
17+
credit = 450.5676
18+
balance = credit - debit
19+
template = t"Credit: {credit:.2f}, Debit: {debit:.2f}, Balance: {balance:.2f}"
20+
21+
22+
# def build_report(template):
23+
# parts = ["Account Report:\n"]
24+
# for item in template:
25+
# if isinstance(item, str):
26+
# parts.append(item.strip(", ").upper())
27+
# else:
28+
# parts.append(f"> ${item.value:{item.format_spec}}")
29+
# parts.append("\n")
30+
# return "".join(parts)
31+
32+
33+
def build_report(template):
34+
parts = ["Account Report:\n"]
35+
for item in template:
36+
match item:
37+
case str() as s:
38+
parts.append(s.strip(", ").upper())
39+
case Interpolation() as i:
40+
parts.append(f"> ${i.value:{i.format_spec}}")
41+
parts.append("\n")
42+
return "".join(parts)
43+
44+
45+
report = build_report(template)
46+
print(report)

0 commit comments

Comments
 (0)