Skip to main content

tplx

Version Python versions License: MIT Docs CI

Render a tree of templates where each file's suffix picks its engine and its stem names what it renders: boot.cfg.j2 is Jinja, boot.cfg.mako is mako, and both answer to boot.cfg. A file no engine claims is copied byte for byte. Documentation: https://jose-pr.github.io/tplx/.

Features

  • One call for every engine — Jinja, mako, Liquid, Handlebars, Mustache, ERB, EPP and a %{NAME} shell-style engine, each rendering the same data.
  • Name by stem, dispatch by suffix — a caller asks for boot.cfg; the file found decides the engine.
  • Several search roots, local or remote, searched in order, plus per-caller candidate names and paths (web01.boot.cfg before boot.cfg).
  • Includes that search the same way — {% include %}, <%include/>, {{> partial}} and the rest resolve through the lookup that loaded the file.
  • One undefined-variable policy (strict, lenient, debug) that means the same thing in every engine that can honour it.
  • Your encoding of the data — a DataEncoder subclass decides what is a structure and how values are written and flattened for the engines that cannot run Python.
  • Byte-exact fallback — an unclaimed file is copied as it is, never decoded.
  • Pluggable — an engine is a class with a suffix list and a priority, registered directly or through the tplx.engines entry point, and checked by the shipped tplx.testing.EngineContract suite.
  • Nothing required — each engine's library is an extra, imported only when a file needs it.

Installation

pip install tplx
Engine Suffixes Install Undefined names Includes
Jinja .j2 .jinja .jinja2 tplx[jinja] strict, lenient, debug {% include %} {% extends %} {% import %} {% from %}
mako .mako tplx[mako] strict, lenient (debug is lenient) <%include/> <%inherit/> <%namespace/>
Liquid .liquid tplx[liquid] strict, lenient, debug {% include %} {% render %}
Handlebars .hbs .handlebars tplx[handlebars] always empty {{> name}}
Mustache .mustache tplx[mustache] always empty {{> name}}
ERB .erb ruby on PATH Ruby's nil —
EPP .epp puppet on PATH Puppet's undef —
shell (%{NAME}) .shtpl — strict, lenient, debug —
copy any other — n/a: the bytes as stored —

Each library-backed engine is an extra of that name (pip install "tplx[jinja,mako]"); the cli extra adds the tplx command.

Each engine keeps its own syntax and defaults. In particular Handlebars and Mustache HTML-escape {{x}} (& becomes &amp;), as their specifications say; write {{{x}}} for the value as it is. The other engines write values unescaped.

Templates and their roots are trusted, in every engine alike: Jinja and mako run Python, ERB and EPP run Ruby and Puppet. What tplx guards is the template name: one that would leave the search paths (.., a backslash, a drive) is refused.

Quick start

from tplx import Loader

loader = Loader(["templates"])
text = loader.render("boot.cfg", {"hostname": "web01"}, release="13")

A caller with its own search order binds it once; includes follow it:

lookup = loader.lookup(
    candidates=lambda name: [f"web01.{name}", name],
    paths=["debian"],  # templates/debian/ before templates/
)
text = lookup.render("boot.cfg", hostname="web01")

Filters, helpers and options go to each engine's own environment:

import shlex

from tplx import JinjaTemplate, Loader

loader = Loader(
    ["templates"],
    configure={JinjaTemplate: lambda env: env.filters.update(quote=shlex.quote)},
)

Command line

pip install "tplx[cli,jinja]"
tplx render templates/boot.cfg.j2 -s hostname=web01      # one file
tplx render boot.cfg -r templates -d host.json -o boot.cfg  # a name, data from JSON
tplx render web01.boot.cfg boot.cfg -r templates         # the first name found
tplx find boot.cfg -r templates                          # which file, which engine
tplx engines                                             # what is registered

-s a.b=v nests and merges into --data; -s n=json:3 passes JSON. Exit status: 0 done, 1 the template or an engine failed, 2 a usage error.

API overview

Module Purpose
tplx Loader, Lookup, the engines, the Template contract and the registry
tplx.exceptions TplxError and its subclasses
tplx.engines the shipped engine classes
tplx.testing EngineContract, the suite every engine passes
tplx.cli the tplx command (cli extra)

Development

python -m venv .venv/3.14
.venv/3.14/bin/python -m pip install -e ".[dev,docs]"   # Scripts/ on Windows
.venv/3.14/bin/python -m pytest -q -rs

Releasing

This project follows Semantic Versioning and keeps a CHANGELOG.md. Pushing a tag matching v* triggers the release workflow: test and dependency-floor gates → build (checking the tag names the version built) → an installed-wheel smoke test and a strict docs build as gates → GitHub release → publish. The release workflow never deploys the docs site itself: for a final release its last job dispatches the docs workflow at the tag, which owns every Pages deploy.

License

MIT — see LICENSE.

Metadata

Release files for tplx 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for tplx 0.1.0
File Size Uploaded
tplx-0.1.0.tar.gz 59.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for tplx 0.1.0
File Interpreter ABI Platform
tplx-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 112.6 kB

Release files / tplx-0.1.0.tar.gz

Download URL tplx-0.1.0.tar.gz
Size 59.1 kB
Tags Source
SHA-256 checksum
How to use checksums
012a7f5cc6ea005365d7aaf09b1ff40f98908eee31a7733e424243d4f949c3a9
BLAKE2b-256 checksum
How to use checksums
9b4997c3e463a6723312f73a08d3f7a1bf7965515c0c639c3dfeeb0d86fafb63
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 Oct 14, 2026.

Transparency log

Release files / tplx-0.1.0-py3-none-any.whl

Download URL tplx-0.1.0-py3-none-any.whl
Size 53.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
129a45e9d1f85a655f1e812c5790be440483c4832203a6967098533181d0d819
BLAKE2b-256 checksum
How to use checksums
95d6edcc1a2df36d30c14193bc1bae7e622bb4d7226cebe0ac4bcb19813ede75
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 Oct 14, 2026.

Transparency log

Release history Release notifications | RSS feed

0.1.2

2 release files

0.1.1

2 release files

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page