Kida ships two t-string tag functions that leverage Python 3.14's native template strings (PEP 750):
| Tag | Purpose | Returns |
|---|---|---|
k() |
Auto-escaping HTML interpolation | str |
r() |
Composable regex with ReDoS validation | ComposablePattern |
Both are available from the top-levelkida package and from kida.tstring.
ThekTag — Auto-Escaping HTML
k() processes a t-string with automatic HTML escaping. Values are escaped unless they implement the __html__() protocol (i.e., they are Markupinstances).
from kida.tstring import k
name = "<script>alert('xss')</script>"
html = k(t"Hello, {name}!")
# 'Hello, <script>alert('xss')</script>!'
Safe Content Passes Through
Objects that implement__html__() (like Markup) are not double-escaped:
from kida import Markup
from kida.tstring import k
safe_html = Markup("<b>Bold</b>")
result = k(t"Content: {safe_html}")
# 'Content: <b>Bold</b>'
Use Cases
- Server-side rendering — Build HTML fragments in Python with auto-escaping
- Email templates — Quick HTML generation without loading a full template
- CLI tools — Generate safe HTML output from user input
from kida.tstring import k
def render_user_card(name: str, bio: str) -> str:
return k(t"""
<div class="card">
<h2>{name}</h2>
<p>{bio}</p>
</div>
""")
# User input is automatically escaped
render_user_card("<script>", "I'm a <b>hacker</b>")
The rTag — Composable Regex
r()composes regex patterns safely by wrapping interpolated values in non-capturing groups. This prevents group index collision and quantifier interference.
from kida.tstring import r
NAME = r"[a-zA-Z_][a-zA-Z0-9_]*"
INTEGER = r"\d+"
pattern = r(t"{NAME}|{INTEGER}")
pattern.compile().match("variable_123")
# <re.Match object; span=(0, 12), match='variable_123'>
ComposablePattern
Ther() tag returns a ComposablePattern— a lazy-compiling regex wrapper with safety validation:
from kida.tstring import ComposablePattern
NAME = ComposablePattern(r"[a-zA-Z_][a-zA-Z0-9_]*")
INTEGER = ComposablePattern(r"\d+")
# Compose with | operator
combined = NAME | INTEGER
print(combined.pattern)
# '(?:[a-zA-Z_][a-zA-Z0-9_]*)|(?:\d+)'
# Compile when ready
regex = combined.compile()
regex.match("hello") # <re.Match object>
| Method | Description |
|---|---|
pattern |
The raw regex pattern string (property) |
compile(flags=0) |
Compile tore.Pattern(cached for flags=0) |
|operator |
Combine patterns with alternation |
ReDoS Validation
Patterns are validated at creation time for known ReDoS-vulnerable constructs (exponential backtracking):
from kida.tstring import ComposablePattern, PatternError
try:
ComposablePattern(r"(a+)+") # Nested quantifiers
except PatternError as e:
print(e)
# Pattern may be vulnerable to ReDoS (exponential backtracking)
Disable validation when you know the pattern is safe:
ComposablePattern(r"(a+)+", validate=False)
Composing with T-Strings
Interpolated values can be strings orComposablePatterninstances:
from kida.tstring import r, ComposablePattern
# String interpolation
IDENT = r"[a-zA-Z_]\w*"
STRING = r"'[^']*'"
token = r(t"{IDENT}|{STRING}")
# ComposablePattern interpolation
ident_pat = ComposablePattern(r"[a-zA-Z_]\w*")
string_pat = ComposablePattern(r"'[^']*'")
token = r(t"{ident_pat}|{string_pat}")
API Reference
Functions
| Function | Signature | Description |
|---|---|---|
k() |
(template: TemplateProtocol) -> str |
Auto-escaping HTML interpolation |
r() |
(template: TemplateProtocol) -> ComposablePattern |
Safe regex composition |
Classes
| Class | Description |
|---|---|
ComposablePattern |
Lazy-compiling regex with ReDoS validation |
PatternError |
Raised for invalid or unsafe patterns |
TemplateProtocol |
Protocol for t-string compatibility |
Import Paths
# From top-level package
from kida import k, r, ComposablePattern
# From tstring module
from kida.tstring import k, r, ComposablePattern, PatternError