reportsmith
A small, dependency-free Python library for building reports programmatically and exporting them to Markdown, a standalone styled HTML document, LaTeX, or (optionally) PDF.
Features
- Fluent builder API with chainable methods and nested sections (
with report.section(...)) - Elements: headings, paragraphs, tables (with alignment and captions), bullet/numbered lists (nestable), code blocks, block quotes, images, horizontal rules, and format-specific raw passthrough
- Inline formatting helpers:
bold(),italic(),code(),link()— render correctly in both formats - Correct escaping everywhere: HTML entities, Markdown table pipes, code fences that widen when the source contains
``` - HTML export ships with a clean embedded stylesheet (light/dark aware) that you can replace with your own CSS
- LaTeX export: a compilable document (pdfLaTeX/XeLaTeX/LuaLaTeX) with booktabs tables, framed code blocks, hyperlinks, and PDF bookmarks — or a body fragment to
\inputinto your own document - Optional PDF export (
pip install reportsmith[pdf], via fpdf2): matching styling, PDF bookmarks from sections, clickable links, auto-detected Unicode system fonts - No required dependencies; Python 3.9+
Installation
pip install -e .
Or just copy the reportsmith/ package into your project — it has no dependencies.
Quick start
from reportsmith import Report, bold, link
report = Report("Q3 Sales Report", author="Jane Doe", subtitle="Quarterly summary")
with report.section("Overview") as s:
s.paragraph(["Revenue was ", bold("up 12%"), " quarter over quarter."])
s.table(
["Region", "Revenue"],
[["EMEA", "$1.2M"], ["APAC", "$0.9M"]],
caption="Revenue by region",
align=["left", "right"],
)
with report.section("Next steps") as s:
s.numbered_list([
"Expand APAC sales team",
["Review ", link("pricing proposal", "https://example.com/pricing")],
])
print(report.to_markdown()) # Markdown string
print(report.to_html()) # standalone HTML page
report.save_markdown("report.md")
report.save_html("report.html")
report.save_latex("report.tex") # compile with pdflatex/xelatex/lualatex
Run python example.py for a fuller demo that writes example_report.md, example_report.html, and example_report.tex.
Documentation
- User Guide — a walkthrough of every feature with examples: sections, inline formatting, tables, lists, raw passthrough, HTML customization, and escaping behavior.
- API Reference — signatures, parameters, and exceptions for every public class and function (reStructuredText, Sphinx-ready).
The docs are also a buildable Sphinx site:
pip install -e .[docs]
python -m sphinx -b html docs docs/_build/html
Then open docs/_build/html/index.html.
API overview
Report(title, author="", date=None, subtitle="")
date accepts a string, datetime.date, or datetime.datetime; it defaults to today.
Builder methods (all chainable, also available on sections):
| Method | Adds |
|---|---|
section(title) |
Nested section; heading level tracks nesting depth. Usable as a context manager. |
heading(text, level=None) |
Explicit heading (level defaults to the container's depth + 1) |
paragraph(content) |
Paragraph |
quote(content) |
Block quote |
code(source, language="") |
Fenced/<pre> code block |
bullet_list(items) / numbered_list(items) |
List; items may be text or a nested ListElement |
table(headers, rows, caption="", align=None) |
Table; align entries are "left", "center", "right" |
image(src, alt="", title="") |
Image |
horizontal_rule() |
Rule |
raw(content, format="both") |
Verbatim content for "markdown", "html", "latex", or "both" (Markdown + HTML) |
add(element) |
Any pre-built element |
Anywhere text is accepted you may pass a plain string or a list mixing strings with bold(), italic(), code(), and link(text, href) spans.
Export
report.to_markdown()→ GitHub-flavored Markdown stringreport.to_html(full_document=True, css=None)→ HTML string;full_document=Falsereturns just the body fragment,css=replaces the default stylesheetreport.to_latex(full_document=True, document_class="article", class_options="11pt,a4paper", preamble="", numbered=False)→ LaTeX source;full_document=Falsereturns just the body,preamble=is appended to the built-in preamblereport.to_pdf(fonts=None, mono_fonts=None)→ PDF bytes (requires thepdfextra); pass TTF path quadruples to control typefacesreport.save_markdown(path)/report.save_html(path, ...)/report.save_latex(path, ...)/report.save_pdf(path, ...)→ write to a file, return thePath
Running tests
The test suite (151 tests) lives in tests/:
python -m pytest
With a coverage report (requires pytest-cov):
python -m pytest --cov=reportsmith --cov-report=term-missing
Changelog
See CHANGELOG.md — the format follows Keep a Changelog.
License
MIT
Metadata
Release files for reportsmith 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| reportsmith-0.2.0.tar.gz | 28.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| reportsmith-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 49.8 kB
Release files / reportsmith-0.2.0.tar.gz
| Download URL | reportsmith-0.2.0.tar.gz |
|---|---|
| Size | 28.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
316f9b60addd87c7bb39c647aa7c6e1130130a14a126597aaa7179a61bbb8caf
|
|
BLAKE2b-256 checksum How to use checksums |
cf9565fde73ca9432ebf84894b9e3ce5a1420bd8241d978c10da08cb59c8ba47
|
| 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 12, 2026.
Transparency logRelease files / reportsmith-0.2.0-py3-none-any.whl
| Download URL | reportsmith-0.2.0-py3-none-any.whl |
|---|---|
| Size | 21.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e4bbee9b50785f141ebb6a160453d1e0c88d3a7424128924caef0f06a0dc8336
|
|
BLAKE2b-256 checksum How to use checksums |
537779e501f7489409822fb35efd7f0336da65e7978a36a5f3cf2925a02f3fda
|
| 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 12, 2026.
Transparency log