AI Skill Report Card

Processing Template Strings

A-85·Aug 14, 2026·Source: Web
14 / 15
Python
# t-strings (t"...") produce Template objects, NOT strings. # Unlike f-strings, interpolated values stay as live objects until you process them. name = "World" template = t"Hello, {name}!" print(type(template)) # <class 'string.templatelib.Template'> # Iterate over strings and interpolations in order for item in template: print(repr(item)) # 'Hello, ' # Interpolation(value='World', expression='name', conversion=None, format_spec='') # '!' # Convert to a plain string manually (no auto-escaping happens for you) result = "".join( str(item.value) if hasattr(item, "value") else item for item in template ) print(result) # "Hello, World!"
Recommendation
Add an example showing error handling when format_spec and conversion conflict (e.g., repr + numeric format spec)
  • Template — the object produced by t"...". Iterable, yielding a mix of str literal segments and Interpolation objects in source order.
    • .strings — tuple of the literal string parts (length = interpolations + 1).
    • .interpolations — tuple of Interpolation objects.
    • .values() — shortcut generator of just the interpolation values.
    • Supports + concatenation with other Template or str objects (returns a Template).
  • Interpolation — represents one {expr} slot. Fields:
    • .value — the evaluated Python object (already evaluated, not lazy).
    • .expression — source text of the expression, e.g. "name" or "x + 1".
    • .conversion"s", "r", "a", or None (from !s/!r/!a).
    • .format_spec — string from :spec, "" if absent (raw, not pre-applied).
  • Key distinction from f-strings: nothing is stringified automatically. You own the conversion/format/escaping logic — this is the entire point of t-strings (safe templating DSLs).
13 / 15

Progress:

  • Identify whether you need a Template (t-string, deferred) or an f-string (immediate string)
  • Write a renderer that walks template.strings / template.interpolations or iterates the Template directly
  • Apply conversion (!s/!r/!a) manually if present
  • Apply format_spec manually (typically via format(value, spec))
  • Apply domain-specific escaping (HTML, SQL, shell) to interpolated values only — never to literal segments
  • Join everything into the final output

Step-by-step renderer pattern

Python
from string.templatelib import Template, Interpolation def render(template: Template, escape=str) -> str: parts = [] for item in template: if isinstance(item, Interpolation): value = item.value if item.conversion == "s": value = str(value) elif item.conversion == "r": value = repr(value) elif item.conversion == "a": value = ascii(value) if item.format_spec: value = format(value, item.format_spec) parts.append(escape(str(value))) else: parts.append(item) # literal text: NOT escaped return "".join(parts)
Recommendation
Include a brief note on Python version requirement (3.14+) for PEP 750 t-strings since this is very new syntax
18 / 20

Example 1: HTML auto-escaping (the canonical t-string use case) Input:

Python
import html def html_escape(template): parts = [] for item in template: if isinstance(item, str): parts.append(item) else: parts.append(html.escape(str(item.value))) return "".join(parts) user_input = "<script>alert(1)</script>" page = t"<p>Comment: {user_input}</p>" print(html_escape(page))

Output:

<p>Comment: &lt;script&gt;alert(1)&lt;/script&gt;</p>

Example 2: Safe SQL parameterization Input:

Python
def to_sql(template): sql_parts = [] params = [] for item in template: if isinstance(item, str): sql_parts.append(item) else: sql_parts.append("?") params.append(item.value) return "".join(sql_parts), tuple(params) name = "Robert'); DROP TABLE students;--" query = t"SELECT * FROM users WHERE name = {name}" sql, params = to_sql(query) print(sql, params)

Output:

SELECT * FROM users WHERE name = ? ("Robert'); DROP TABLE students;--",)

Example 3: Inspecting format spec and conversion Input:

Python
value = 3.14159 t_obj = t"{value!r:.2f}" interp = t_obj.interpolations[0] print(interp.value, interp.conversion, interp.format_spec)

Output:

3.14159 r .2f

(Note: conversion and format_spec are metadata only — applying both is your responsibility, e.g. format(repr(value), ".2f") would error since repr returns a str; typically you choose one or handle order deliberately.)

Recommendation
Show a more complex DSL example combining multiple interpolations with different escaping needs in one template
  • Treat Template as an AST-like object, not a string — never call str(template) expecting sensible output (it does not exist as a stringification API; iterate instead).
  • Centralize escaping in one render/escape function per output context (HTML, SQL, shell, logging) rather than escaping ad hoc.
  • Preserve literal .strings segments verbatim — only transform Interpolation.value.
  • When building a DSL, validate .expression only for debugging/error messages, not as executable logic — .value is already evaluated.
  • Use .values() when you only need the raw interpolated objects and don't care about surrounding literals or metadata.
  • Combine Template objects with + to compose reusable partial templates before final rendering.
  • Assuming auto-conversion: unlike f-strings, t"{x}" does not stringify xinterpolation.value keeps its original type (int, list, custom object, etc.).
  • Escaping literal segments: only escape Interpolation values; escaping the plain str segments from .strings will double-escape or corrupt intended markup.
  • Ignoring format_spec/conversion: these are captured as metadata strings, not auto-applied — forgetting to apply them silently drops formatting like .2f or !r.
  • Using t-strings where f-strings suffice: if no deferred processing/escaping is needed, an f-string is simpler and produces a str directly.
  • Mutating and reusing Interpolation objects: they're immutable value carriers; build new Template/output rather than trying to patch fields in place.
0
Grade A-AI Skill Framework
Scorecard
Criteria Breakdown
Quick Start
14/15
Workflow
13/15
Examples
18/20
Completeness
18/20
Format
15/15
Conciseness
14/15