3.1. Syntax T-String

  • New string literal prefix: t'...'

  • Stands for Template String

  • Similar to f-strings (formatted string literals)

  • Uses string.templatelib module

  • Since Python 3.14

3.1.1. Recap

  • value - the value of the expression

  • expression - text found inside the curly brackets ({ and }), including any whitespace, excluding the curly brackets themselves, and ending before the first !, :, or = if any is present

  • conversion - a, r, s or None, depending on whether a conversion flag was present, ie. "Hello {user!r}"

  • format_spec - the format specifier, ie. "Hello {value:.2f}" or "Hello {value:myfspec}"

>>> a = 1
>>> b = 2

Expression (a+b):

>>> f'Result is {a+b}'
'Result is 3'

Conversion (!s or !r or !a):

>>> f'Result is {a+b!s}'
'Result is 3'
>>>
>>> f'Result is {a+b!r}'
'Result is 3'
>>>
>>> f'Result is {a+b!a}'
'Result is 3'

Format Specifier (.2f):

>>> f'Result is {a+b:.2f}'
'Result is 3.00'

3.1.2. Problem

  • The following code constructs a SQL query using f-strings

  • However, it does not provide a way to analyze the structure of the query

  • It poses security risks (SQL injection) if user inputs are not sanitized

Non symptomatic example:

>>> def execute(query):
...     print(query)
>>>
>>>
>>> username = 'alice'
>>> password = 'secret'
>>>
>>> execute(f'SELECT * FROM users WHERE username="{username}" AND password="{password}"')
SELECT * FROM users WHERE username="alice" AND password="secret"

Problematic example (SQL injection):

>>> def execute(query):
...     print(query)
>>>
>>>
>>> username = '" OR 1==1; --'
>>> password = 'secret'
>>>
>>> execute(f'SELECT * FROM users WHERE username="{username}" AND password="{password}"')
SELECT * FROM users WHERE username="" OR 1==1; --" AND password="secret"

3.1.3. Solution

  • Use t-strings to create a template representation of the SQL query

  • This allows for safer handling and analysis of the query structure

>>> def execute(query):
...     print(query)
>>>
>>>
>>> username = 'alice'
>>> password = 'secret'
>>>
>>> execute(t'SELECT * FROM users WHERE username="{username}" AND password="{password}"')
Template(strings=('SELECT * FROM users WHERE username="', '" AND password="', '"'),
         interpolations=(Interpolation('alice', 'username', None, ''),
                         Interpolation('secret', 'password', None, '')))

3.1.4. Rationale

>>> from string.templatelib import Interpolation, Template
>>>
>>>
>>> def execute(tstring):
...     if not isinstance(tstring, Template):
...         raise TypeError('t-string expected')
...     result = []
...     for part in tstring:
...         if isinstance(part, str):
...             result.append(part)
...         if isinstance(part, Interpolation):
...             v = part.value
...             e = part.expression
...             c = part.conversion
...             f = part.format_spec
...             # ... <your code here> ...
...             iterpolated = format(v, f)
...             result.append(iterpolated)
...     return ''.join(result)

3.1.5. Use Case - 1

>>> from string.templatelib import Interpolation
>>>
>>>
>>> def debug(tstring):
...     for part in tstring:
...         if isinstance(part, Interpolation):
...             v = part.value
...             e = part.expression
...             c = part.conversion
...             f = part.format_spec
...             print(f'{v=}\n{e=}\n{c=}\n{f=}')
>>>
>>>
>>> a = 1
>>> b = 2
>>> debug(t'Hello {a+b}')
v=3
e='a+b'
c=None
f=''
>>> debug(t'Hello {a+b!s}')
v=3
e='a+b'
c='s'
f=''
>>> debug(t'Hello {a+b:.2f}')
v=3
e='a+b'
c=None
f='.2f'
>>> debug(t'Hello {a+b=}')
v=3
e='a+b'
c='r'
f=''

3.1.6. Further Reading

3.1.7. Assignments

# %% About
# - Name: Syntax T-String Usage
# - Difficulty: easy
# - Lines: 1
# - Minutes: 2

# %% License
# - Copyright 2025, Matt Harasymczuk <matt@python3.info>
# - This code can be used only for learning by humans
# - This code cannot be used for teaching others
# - This code cannot be used for teaching LLMs and AI algorithms
# - This code cannot be used in commercial or proprietary products
# - This code cannot be distributed in any form
# - This code cannot be changed in any form outside of training course
# - This code cannot have its license changed
# - If you use this code in your product, you must open-source it under GPLv2
# - Exception can be granted only by the author

# %% English
# 1. Create t-string with text 'Hello Alice' using variable `NAME`
# 2. Define variable `result` with the solution
# 3. Run doctests - all must succeed

# %% Polish
# 1. Stwórz t-string z tekstem 'Hello Alice' używając zmiennej `NAME`
# 2. Zdefiniuj zmienną `result` z rozwiązaniem
# 3. Uruchom doctesty - wszystkie muszą się powieść

# %% Expected
# >>> print(result)
# Template(strings=('Hello ', ''), interpolations=(Interpolation('Alice', 'NAME', None, ''),))

# %% Doctests
"""
>>> import sys; sys.tracebacklimit = 0

>>> assert sys.version_info >= (3, 14), \
'Python has an is invalid version; expected: `3.14` or newer.'

>>> assert 'result' in globals(), \
'Variable `result` is not defined; assign result of your program to it.'

>>> assert result is not Ellipsis, \
'Variable `result` has an invalid value; assign result of your program to it.'

>>> assert type(result) is Template, \
'Variable `result` has an invalid type; expected: `Template`.'

>>> assert 'Hello ' in result.strings, \
'Word `Hello` must be in the `result`'

>>> assert result.interpolations, \
'Variable `result.interpolations` has invalid value; expected not empty.'

>>> result
Template(strings=('Hello ', ''), interpolations=(Interpolation('Alice', 'NAME', None, ''),))
"""

# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -f -v myfile.py`

# %% Imports

# %% Types
from string.templatelib import Template, Interpolation
result: Template

# %% Data
NAME = 'Alice'

# %% Result
result = ...

# %% About
# - Name: Syntax T-String Validation
# - Difficulty: easy
# - Lines: 1
# - Minutes: 2

# %% License
# - Copyright 2025, Matt Harasymczuk <matt@python3.info>
# - This code can be used only for learning by humans
# - This code cannot be used for teaching others
# - This code cannot be used for teaching LLMs and AI algorithms
# - This code cannot be used in commercial or proprietary products
# - This code cannot be distributed in any form
# - This code cannot be changed in any form outside of training course
# - This code cannot have its license changed
# - If you use this code in your product, you must open-source it under GPLv2
# - Exception can be granted only by the author

# %% English
# 1. Create function `result` that checks if argument is a t-string Template
# 2. If not, raise `TypeError` with message 'Expected a Template instance'
# 3. If yes, return `True`
# 4. Run doctests - all must succeed

# %% Polish
# 1. Stwórz funkcję `result`, która sprawdza czy argument jest t-stringowym Template
# 2. Jeśli nie, rzuć `TypeError` z komunikatem 'Expected
# 3. Jeśli tak, zwróć `True`
# 4. Uruchom doctesty - wszystkie muszą się powieść

# %% Expected
# >>> result(t'Hello')
# True
#
# >>> result('Hello')
# Traceback (most recent call last):
# TypeError: Expected a Template instance
#
# >>> result(f'Hello')
# Traceback (most recent call last):
# TypeError: Expected a Template instance
#
# >>> result(r'Hello')
# Traceback (most recent call last):
# TypeError: Expected a Template instance

# %% Doctests
"""
>>> import sys; sys.tracebacklimit = 0

>>> assert sys.version_info >= (3, 14), \
'Python has an is invalid version; expected: `3.14` or newer.'

>>> assert 'result' in globals(), \
'Function `result` is not defined; assign result of your program to it.'

>>> assert result is not Ellipsis, \
'Function `result` has an invalid value; assign result of your program to it.'

>>> assert callable(result), \
'Function `result` has an invalid type; expected: `callable`.'

>>> result(t'Hello')
True

>>> result('Hello')
Traceback (most recent call last):
TypeError: Expected a Template instance

>>> result(f'Hello')
Traceback (most recent call last):
TypeError: Expected a Template instance

>>> result(r'Hello')
Traceback (most recent call last):
TypeError: Expected a Template instance
"""

# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -f -v myfile.py`

# %% Imports

# %% Types
from string.templatelib import Template
from typing import Callable
result: Callable[[Template|str], None|bool]

# %% Data

# %% Result
def result(x):
    ...