Skip to main content

postext for Python

Typeset books from Python with Postext: a print-ready PDF, HTML pages, an EPUB, page images, a Word document or an InDesign package from a .postext book, a book folder or loose Markdown files.

pip install postext
import postext

report = postext.pdf("book.postext", out="book.pdf", set={"page.dpi": 300})
print(report.output.pages, "pages")
for warning in report.warnings:
    print(warning)            # warning missingFont (chapters/02.md:14): …

pdf = postext.pdf_bytes(open("book.postext", "rb").read())   # bytes in, bytes out

The package drives the self-contained postext command line, the same executable as brew install drnachio/postext/postext or npx postext-cli: the layout is the Sandbox's, and the same book breaks into the same pages. The wheel is pure Python with no dependencies. The executable of your system (185 to 230 MB, too large for a wheel) is downloaded on first use from the GitHub Release of the package's version, checked against the release's SHA256SUMS and kept in the cache:

System Executable
macOS, Apple silicon / Intel postext-macos-arm64 / postext-macos-x64
Linux x86-64 / ARM64 (glibc) postext-linux-x64 / postext-linux-arm64
Linux x86-64, musl (Alpine) postext-linux-x64-musl
Windows x64 (and ARM, emulated) postext-windows-x64.exe
Environment variable Effect
POSTEXT_BIN Run this executable instead (Homebrew, Scoop, a local build); nothing is downloaded
POSTEXT_CACHE_DIR Cache folder (default ~/.cache/postext, %LOCALAPPDATA%\postext\cache on Windows); executables go in bin/<version>/, downloaded fonts in fonts/
POSTEXT_RELEASE_URL Download from a mirror: a URL with {version} where the release's files are

python -m postext pdf book.postext -o book.pdf runs the command line itself.

Commands

Every command of the command line is a function. Each runs the command with --json and returns its report.

Function Command Returns
pdf(book, out=…, pdfx=…, profile=…, color_space=…) postext pdf Report
html(book, out=…, mode=…, assets=…) postext html Report
epub(book, out=…, layout=…, cover=…) postext epub Report
image(book, page="#1", out=…, dpi=…, format=…) postext image ImageReport
images(book, out="pages/", pages=…, pattern=…) postext images Report
docx(book, out=…, variant=…) postext docx Report
import_docx(docx, book=None, out=…, dry_run=…) postext import-docx ImportDocxReport
idml(book, out=…, images=…, lines=…, spreads=…, fonts=…) postext idml Report
import_idml(idml, out=…, layout=…, links=…, document=…) postext import-idml ImportIdmlReport
pack(book, out=…) / unpack(bundle, out=…) postext pack / unpack Report / UnpackReport
design(book, out=…, parts=…, design_name=…) postext design DesignReport
info(book, pages=True) postext info InfoReport
check(book, strict=True) postext check CheckReport
build(book, pdf=…, html=…, epub=…, images=…, docx=…, idml=…) postext build Report

book is a path (a .postext file, a book folder, a Markdown file), a list of Markdown files (the chapters, in order), or the bytes of a .postext bundle. The commands that read a book take the book options:

postext.pdf(
    ["01.md", "02.md"],
    out="notes.pdf",
    name="Notes",                      # --name
    config={"page": {"sizePreset": "A5"}},   # --config (a dict or a file)
    set={"bodyText.fontSize.value": 11},     # --set, one per key
    locale="es",                       # --locale
    chapters=range(1, 3),              # --chapters 1-2 (also 3, "1,3-5", [1, 3])
    resources="img/", fonts="fonts/",  # --resources, --fonts
    font_dirs=["~/Fonts"],             # --font-dir
    offline=True,                      # --offline: never download fonts
    design="novel.postext",            # --design: a design file (a path or bytes), or another book
    design_parts=["page", "text"],     # --design-parts page,text
    composition="auto",                # --composition: the composition rules of the book's language (or "es", "en-GB"…)
)

design(book, out="novel.postext", parts=["page", "text", "headings"]) takes a book's design into a design file, and design= puts it on any other book. In idml, fonts=True is the switch that writes the font files beside the package, not the book option. import_idml reads a bare .idml or a zipped InDesign package, as a path or as bytes (then give out, and links for the linked pictures).

Reports and warnings

A Report has ok, command, version, exit_code, pages, book (name, id, locale, chapters), outputs (Output: kind, path, size, pages), warnings (Diagnostic: kind, message, severity, at, page, data), timings and raw, the whole JSON object. InfoReport adds chapters, resources and fonts; CheckReport adds passed, error_count, warning_count, contrast, reflow and preflight; DesignReport adds name and parts; ImportIdmlReport adds layout (pages or flow), reason, chapters, quality (the import report), fonts, missing_links and package.

Bytes out

out="-" (or postext.STDOUT) writes to stdout and returns the bytes in report.content; pdf_bytes, html_bytes, epub_bytes, image_bytes, docx_bytes, idml_bytes, pack_bytes and design_bytes return them directly (idml with linked pictures or fonts=True needs a file). A book given as bytes with no out comes back as bytes.

Errors

Exception When
PostextError The command failed (exit code 1); err.report and err.stderr say why
UsageError A wrong option or value (exit code 2)
ProblemsFound check found an error (any warning with strict), or import_docx could not apply an edit (exit code 3); raise_on_problems=False returns the report instead
BinaryNotFound No executable for this system, a failed download or checksum, or a POSTEXT_BIN that is not a file

One executable, many runs

postext.Postext(binary=None, cwd=None, env=None, timeout=None, offline=None, font_dirs=None) has the same methods with its own executable, folder, environment and timeout. Postext().run(["build", "book/", "--pdf", "b.pdf", "--watch"], capture=False) runs any command as typed.

Each call starts the executable again. A mode that keeps one engine running between calls is planned.

Docs

MIT licence.

Metadata

Release files for postext 1.82.1

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

Source distribution (sdist)

Source distribution for postext 1.82.1
File Size Uploaded Provenance Actions
postext-1.82.1.tar.gz 27.7 kB With provenance Details for postext-1.82.1.tar.gz

Built distribution (wheel)

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

Total release size: 54.2 kB

Release files / postext-1.82.1.tar.gz

Download URL postext-1.82.1.tar.gz
Size 27.7 kB
Tags Source
SHA-256 checksum
How to use checksums
124b4ec01590817ea01fb000115ef76f28581349871c03dd69e9e80d1edb5b41
BLAKE2b-256 checksum
How to use checksums
d99cada1344633c1160e9fcff638245611f3850c083239dfa2368ff348b7e7e8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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 Nov 13, 2026.

Transparency log

Release files / postext-1.82.1-py3-none-any.whl

Download URL postext-1.82.1-py3-none-any.whl
Size 26.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
36ed08c6d816680bdfe081b312dfd1dd5770c9f37ae0bfb1128bd69ede8abead
BLAKE2b-256 checksum
How to use checksums
fd12dfbcfda18edd92ece279506ff07dc7c96c7599c2d0adf20deca22d5d3a21
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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 Nov 13, 2026.

Transparency log

Security for postext 1.82.1

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.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for postext-1.82.1.tar.gz

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 Nov 13, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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