Maintainer update: Open to opportunities. koxudaxi.dev
Parser-first JSON, TOML, and YAML backends for PEP 750 – Template Strings t-strings.
T-strings (introduced in Python 3.14) give you f-string convenience with
structured access to interpolation values via
string.templatelib.Template.
This project builds on that: write templates that look like the target format,
and get validated text or parsed Python data back.
Pick the format you need:
| Package | Format |
|---|---|
| json-tstring | JSON |
| toml-tstring | TOML |
| yaml-tstring | YAML |
tstring-core (shared runtime) and tstring-bindings (native extension) are
pulled in automatically — you never need to install them directly.
Requires Python 3.14+.
The Python packages depend on tstring-bindings, a native extension built with
PyO3. Release automation currently publishes wheels for Linux x86_64 GNU,
macOS Apple Silicon, and Windows x86_64. Other environments require a local
Rust 1.94.0 toolchain build.
Install the backend you need:
pip install json-tstring
pip install toml-tstring
pip install yaml-tstringOr with uv:
uv add json-tstring
uv add toml-tstring
uv add yaml-tstringEach package pulls in tstring-core and tstring-bindings automatically.
from yaml_tstring import render_data, render_text
name = "api"
replicas = 3
labels = {"app": "api", "team": "platform"}
env = {"LOG_LEVEL": "info", "WORKERS": "4"}
ports = [8080, 8443]
template = t"""\
service:
name: {name}
replicas: {replicas}
labels: {labels}
env: {env}
ports: {ports}
"""
# render_data: t-string -> parsed Python data
data = render_data(template)
# {'service': {'name': 'api',
# 'replicas': 3,
# 'labels': {'app': 'api', 'team': 'platform'},
# 'env': {'LOG_LEVEL': 'info', 'WORKERS': '4'},
# 'ports': [8080, 8443]}}
# render_text: t-string -> valid YAML text
text = render_text(template)
# service:
# name: "api"
# replicas: 3
# labels:
# "app": "api"
# "team": "platform"
# env:
# "LOG_LEVEL": "info"
# "WORKERS": "4"
# ports:
# - 8080
# - 8443JSON and TOML work the same way — json_tstring.render_data(),
toml_tstring.render_text(), etc.
t-linter is a linter, formatter, and
LSP server for t-strings. It uses the same Rust backends as this project for
check and format.
pip install t-linterCheck templates for errors:
t-linter check src/Format JSON / TOML / YAML template literals:
t-linter format src/Start the LSP server for real-time editor diagnostics:
t-linter lspA VSCode extension is also available.
The Rust crates also expose parser-first check and format entry points for
tools that already tokenize template strings themselves, such as LSP servers and
linters.
use tstring_json::{check_template, format_template};
use tstring_syntax::{TemplateInput, TemplateInterpolation, TemplateSegment};
let template = TemplateInput::from_segments(vec![
TemplateSegment::StaticText("{\"name\": ".to_owned()),
TemplateSegment::Interpolation(TemplateInterpolation {
expression: "name".to_owned(),
conversion: None,
format_spec: String::new(),
interpolation_index: 0,
raw_source: Some("{name}".to_owned()),
}),
TemplateSegment::StaticText("}".to_owned()),
]);
check_template(&template)?;
let text = format_template(&template)?;
assert_eq!(text, "{\"name\": {name}}");Available on each backend crate:
check_template_with_profile(...) -> BackendResult<()>check_template(...) -> BackendResult<()>format_template_with_profile(...) -> BackendResult<String>format_template(...) -> BackendResult<String>
format_* requires every interpolation to include raw_source, because the
formatter preserves {expr!r:spec} verbatim instead of reconstructing it from
parsed fields. The formatter returns canonical JSON/TOML/YAML text; it does not
preserve comments or original whitespace.
Requires Python 3.14, uv, and Rust 1.94.0.
uv sync --group devcargo test --manifest-path rust/Cargo.toml --workspace --tests
uv run --group dev pytest -q
uv run --group dev ruff check .
uv run --group dev ty check json-tstring/src toml-tstring/src yaml-tstring/src tstring-core/srcrust/ Rust workspace and native bindings
tstring-core/ shared Python runtime
json-tstring/ JSON wrapper
toml-tstring/ TOML wrapper
yaml-tstring/ YAML wrapper
examples/ runnable examples
conformance/ profile manifests and fixture slices
docs/ support matrix and conformance notes
Each backend accepts a profile argument. Defaults:
- JSON:
rfc8259 - TOML:
1.1(also supports1.0) - YAML:
1.2.2
See Backend Support Matrix and Spec Conformance for details.
Python and Rust packages are published automatically via GitHub Actions when a version tag is pushed.
- PEP 750 – Template Strings
string.templatelib— Template String Support- What's New In Python 3.14
- t-linter — Linter, formatter, and LSP for t-strings