Skip to content

Caxton

Declarative document generation for Python.

Caxton lets you describe what a document contains and what its values mean. The compiler and the selected renderer decide where everything goes and how the target format represents it.

Pre-alpha

Caxton is under active development and is not ready for production use. The delivered surface is the spreadsheet document family rendered to XLSX; see Architecture for the exact boundary.

A first document

from caxton import render, sheet, spreadsheet, table, text, write

rows = [{"name": "Ada Lovelace"}, {"name": "Grace Hopper"}]

report = spreadsheet(
    sheet(
        "People",
        table(
            rows,
            text("name").titled("Name"),
        ),
    ),
)

result = render(report)

write(report, "people.xlsx")

What you get

  • Semantic, not physical

    Columns carry semantic types — money, percentage, date, duration — instead of number formats. The renderer chooses the representation.

  • Immutable specifications

    Every factory returns a frozen node and every fluent method returns a new one, so a report factory can be reused for different row sets without copying or mutation.

  • Lazy data

    Building and validating a document never reads a row. One-shot sources are tracked and a hidden second pass is rejected instead of silently producing an empty table.

  • Testable output

    caxton.testing inspects intent, compiled layout, and the finished artifact — without exposing OpenPyXL or XlsxWriter objects.

Where to go next