-
Notifications
You must be signed in to change notification settings - Fork 0
Home
PyTeX generates LaTeX from Python. You build a document as a tree of typed TeX
nodes and render it to a .tex file — or you drop inline Python into an existing
.tex source and have it evaluated at render time. Either way the output is a
plain .tex file, and --build hands that to tectonic
to get a PDF.
The point of the node tree is that a document stays type-checkable: every node is
an immutable dataclass with a .rendered property, and the public factories are
named after the LaTeX control sequences they emit (Section, Bold, Frac,
Title, …), so the Python reads like the LaTeX it produces. Nodes also carry
their own package requirements, so the preamble is assembled from whatever the
body actually uses — you never hand-maintain a \usepackage list.
from pytex.commands.builtin import Bold, Emph, Section, Title, MakeTitle
from pytex.model.concat import Concat
from pytex.model.document import Document
from pytex.model.math import DisplayMath, Frac
__pytex__ = Document(
preamble=Title("PyTeX Example"),
body=Concat(
MakeTitle(),
Section("Text"),
"A paragraph with ", Bold("bold"), " and ", Emph("emphasised"), " words.",
Section("Math"),
DisplayMath(Concat("x = ", Frac("-b", "2a"))),
),
)pytex example.tex.py # -> build/example.out.tex
pytex example.tex.py --build # -> build/example.out.pdfBare strings are coerced to text nodes and LaTeX-escaped, so you rarely have to
think about escaping &, %, _ and friends.
Requires Python 3.13+. Pick whichever fits:
-
Standalone binary — each release
ships
pytexbinaries for Linux/macOS/Windows with no Python or pip needed. The binary bundles its own interpreter plus common data packages (numpy, pandas, openpyxl/calamine, Pillow, PyYAML), so a document canimportthose without installing anything. It's built on Python 3.14, sotex(t"...")template strings work even on a machine that only has 3.13 or no Python at all. -
pipx —
pipx install pytex-preprocessorto get thepytexcommand on your PATH in an isolated environment. -
pip —
pip install pytex-preprocessorinto whatever environment you like. -
Dev — clone, then
python -m venv venv && . venv/bin/activateandpip install -e .(add[dev]for pytest, ruff, basedpyright).
-
tectonic is fetched on first
--build. You don't install it yourself. If it isn't onPATH, the build downloads a self-contained binary into a temp folder and reuses it. The first build is slow because tectonic also pulls its TeX bundle into a cache ($XDG_CACHE_HOME/Tectonic, or~/.cache/Tectonic); later builds hit that cache and are fast. The cache survives across runs — wipe it only if a bundle gets corrupted. -
3.13 vs 3.14 for t-strings. The core library runs on 3.13. The
PEP 750
tex(t"...")template-string entry point only exists on 3.14, because that's where t-strings landed.texis simply not exported on 3.13. The standalone binary sidesteps this — it's a 3.14 build, so t-string documents work regardless of the host Python. -
inkscapeis needed only forSVGimage conversion, andmakeindex(from a TeX distribution) only to resolve glossaries/acronyms. Both are optional; you'll get a clear error if a document needs one and it's missing.
-
CLI and input modes — the
pytexcommand, the three input kinds (.tex.py,.py.tex,.md),--build,--variant, the flags. - Markdown to PDF — variants, frontmatter, GitHub callouts, citations/bibliographies, the typographic extras.
- Node and factory API — how the tree works and the factories you'll reach for most, including the size switches.
-
Blob API (pytex_api) —
render_blobfor services: source bytes in, PDF bytes out, with trust levels and a Podman sandbox for untrusted input.