templisafe
Template-as-Code for safe, validated rendering workflows.
templisafe is not another template engine. It is a framework built around
template engines such as Jinja or Django to make templating safer, more
repeatable and easier to operate.
The project applies an Infrastructure-as-Code mindset to templating: templates, schemas, concrete values and execution settings can be described as explicit resources, loaded from configurable sources, validated before rendering and processed through a minimal public API.
Why
Templating is often simple at the beginning: one template string, one dictionary of values, one render call. It becomes harder to control when templates are used for SQL queries, configuration files, prompts, reports, messages, deployment manifests or any other generated artifact that needs consistency.
templisafe helps when you want:
- template variables to have an explicit contract.
- values to be validated before rendering.
- multiple parameterizations of the same template.
- schemas and variants to live in normal configuration files.
- templates and values to be loaded from files, HTTP endpoints, cloud services or custom sources.
- a stable API that does not depend on one template engine or one configuration language.
Core Idea
A templisafe workflow is built from five concepts.
Template
The target text to produce. It can represent any file or text-based artifact: SQL, Markdown, HTML, prompts, configuration files or plain text. The rendering syntax is delegated to a template engine.
Schema
The contract associated with a template. A schema defines the variables accepted by the template, including their types and optional constraints. Schema files are parsed from supported configuration languages and validation is powered by Pydantic.
Variant
A concrete set of values for a template. One template can have many variants, so the same template can be rendered for different environments, customers, queries or use cases. Variants are also configuration resources, so they can be written and versioned in supported formats such as YAML, JSON, TOML or XML without changing the templating workflow.
Source
The abstraction used to load templates, schemas, variants and settings. Sources
can be inline values, local files, HTTP resources, cloud resources or custom
implementations provided by the user. In every case, the library only needs a
source implementation able to return content through the read method.
Settings
The configuration layer used to customize library components. Settings can tune sources, parsers, template engines, executors, compilers and renderers. They can be passed directly or loaded from sources, so advanced behavior can be stored in files and versioned together with templates, schemas and variants. Defaults are provided for every component, so simple workflows require little configuration.
Design Principles
- Template-as-Code: templates, schemas and variants are treated as explicit, versionable resources.
- Engine independence: Jinja is supported by default, Django is available, and custom engines can be integrated through inheritance.
- Configuration independence: schemas, variants and settings can be expressed in supported configuration formats without changing the public workflow.
- Source independence: the API works with source abstractions rather than only local files or in-memory strings.
- Progressive configuration: defaults keep the simple path small, while the
Settingsabstraction allows any component to be customized and versioned. - Minimal public API: compile, validate and render are the fundamental operations; build combines them into one workflow.
Supported Capabilities
| Area | Supported |
|---|---|
| Template engines | Jinja by default, Django support, custom engines |
| Schema / variant formats | YAML, JSON, TOML, XML |
| Sources | Inline, local files, HTTP resources and custom sources |
| Validation | Pydantic-backed types, defaults and constraints |
| Customization | Versionable settings for sources, parsers, engines, executors, compilers and renderers |
Installation
pip install templisafe
Quick Start
from templisafe import ContentType, SourceSettings, TemplaterFactory
template = SourceSettings.create(
kind="inline",
content="Hello {{ name }}!",
content_type=ContentType.TEXT,
)
schema = SourceSettings.create(
kind="inline",
content="""
schema:
name: str
""",
content_type=ContentType.YAML,
)
variants = SourceSettings.create(
kind="inline",
content="""
variants:
- name: italy
bindings:
name: Italy
- name: world
bindings:
name: World
""",
content_type=ContentType.YAML,
)
templater = TemplaterFactory().create()
build = templater.build(template=template, schema=schema, variants=variants)
for name in sorted(build.rendering.rendered.names):
print(build.rendering.rendered[name].rendered_str)
Output:
Hello Italy!
Hello World!
Schemas can also define constraints that are enforced before rendering:
schema:
score:
type: int
constraints:
gt: 0
lt: 101
name:
type: str
constraints:
max_length: 40
Advanced configuration can use the same source model. Defaults are available for every component, but settings can be moved to files or remote sources when a workflow needs to be versioned more explicitly:
engine_settings = SourceSettings.create(
kind="inline",
content="engine_kind: jinja",
content_type=ContentType.YAML,
)
build = templater.build(
template=template,
schema=schema,
variants=variants,
template_engine=engine_settings,
)
Public API
The public API is centered on the Templater abstraction:
compile(template, schema=None)compiles a template and its optional schema.validate(compiled, variants)validates variant values without rendering.render(compiled, variants)validates and renders the variants.build(template, variants, schema=None)runs compile, validate and render as one workflow.
Inputs can be provided directly, through concrete source objects or through
serializable SourceSettings.
When Not To Use It
For a one-off template rendered from an in-memory dictionary, calling the
template engine directly is probably enough. templisafe is useful when
templates become reusable assets and need contracts, validation, multiple
variants, configurable sources or repeatable workflows.
Documentation
- User guide: public API, source types, schemas, variants and diagnostics.
- Architecture: internal modules, task pipeline, services, providers and extension points.
- Examples: practical examples.
- Contributing: development setup, tests and contribution workflow.
Development
pip install -e ".[dev]"
python -m pytest -c test/pytest.ini -q
python -m ruff check .
python -m mypy src
License
templisafe is open-source software licensed under the MIT License. See the license for more details.
Metadata
Release files for templisafe 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| templisafe-0.1.1.tar.gz | 73.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| templisafe-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 199.9 kB
Release files / templisafe-0.1.1.tar.gz
| Download URL | templisafe-0.1.1.tar.gz |
|---|---|
| Size | 73.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f38deaf7906400746173a31deeee2b6be39e2f5b9c4124a5f85d90160131d5dc
|
|
BLAKE2b-256 checksum How to use checksums |
62b5f03e9281cbe0bd7846608b0a12c5d7460602e85c9e98c2ad1d1e28e1bdbf
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 17, 2026.
Transparency logRelease files / templisafe-0.1.1-py3-none-any.whl
| Download URL | templisafe-0.1.1-py3-none-any.whl |
|---|---|
| Size | 126.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ecc8b5a276a5bb7aa8c3200918c38e022cc0430cfacad7b5157220d262ea336f
|
|
BLAKE2b-256 checksum How to use checksums |
2f4db1e07f1b481a8231beface4486c8579cbb869bc2a4dafce0a03aa5a04a0f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 17, 2026.
Transparency log