Skip to main content

Composable PDF building blocks (tables, headers, footers, title pages, tile grids) built on ReportLab.

Project description

pdfblox

Composable PDF building blocks for report generation, built on ReportLab. pdfblox turns structured data and images into finished PDF reports — styled tables, page headers/footers, title pages, and tile grids.

Design

pdfblox is the PDF-generation half of a larger report-writing system. It deliberately knows nothing about where data comes from:

┌──────────────────────────────────────────────────────────────┐
│  Integration wrapper  (owns .env / parameter injection)        │
│                                                                │
│   ┌─────────────────────┐         ┌────────────────────────┐  │
│   │  Data-source library │  data   │      pdfblox           │  │
│   │  (e.g. Some REST)    │ ──────▶ │  (this library)        │  │
│   │  fetch + render      │ images  │  build the PDF         │  │
│   └─────────────────────┘         └────────────────────────┘  │
└──────────────────────────────────────────────────────────────┘

Consequences of this boundary:

  • One dependency: reportlab. No plotly, no kaleido, no networking.
  • No dotenv, no os.getenv. All configuration enters through explicit function arguments and *Config dataclasses. Environment/credential loading belongs to the integration layer above.
  • Images come in as bytes or flowables. A logo is logo_data: bytes or a logo_path; a chart is a ready-made ReportLab Image. pdfblox never fetches or renders them.

Documentation

  • AI_REPORT_AUTHORING.md — how to author a report with pdfblox (block reference, recipes, pitfalls, a full template). The guide to read when generating report scripts.
  • CLAUDE.md — how to develop the library itself (boundary rules, conventions, how to add a block).

Installation

pip install -e .

Building Blocks

Block Module Key API
Styled table pdfblox.tables ColumnConfig, TableConfig, create_table
Grouped (banded) table pdfblox.tables GroupBandConfig, grouped_table
Key/value table pdfblox.tables KeyValueConfig, create_keyvalue_table
Text & headings pdfblox.text TextConfig, paragraph, heading
Lists pdfblox.lists ListConfig, bullet_list, numbered_list
Image pdfblox.images make_image
Charts (native vector) pdfblox.charts ChartConfig, bar_chart, line_chart, pie_chart, scatter_chart
Layout primitives pdfblox.layout spacer, divider, CalloutConfig, kpi_callout, PlaceholderConfig, placeholder_box
Page header pdfblox.header HeaderConfig, draw_page_header
Page footer pdfblox.footer FooterConfig, draw_page_footer
Title / cover page pdfblox.document TitlePageConfig
Tile grid pdfblox.document TileGridConfig, build_tile_grid
Document assembly pdfblox.document PdfConfig, build_pdf, build_paginated_pdf
Fluent builder pdfblox.report Report
Theme pdfblox.theme Theme
Theme presets pdfblox.themes get_theme, available_themes, corporate_blue, slate_gray, forest_green, burgundy, teal, graphite
Unicode fonts pdfblox.fonts use_unicode_fonts, register_font
ReportLab value re-exports pdfblox.primitives colors, HexColor, inch, cm, mm, letter, legal, A4, A3, landscape, portrait, PageBreak
Date / OS helpers pdfblox.utils parse_timestamp, normalize_date, blank_to_none, open_file_in_windows

No import reportlab needed: value re-exports

The generic ReportLab values a report reaches for — page sizes, units, and colours (plus the PageBreak flowable) — are re-exported from pdfblox, so a report script needs no direct import reportlab:

from pdfblox import letter, landscape, inch, colors, HexColor, PageBreak

PAGE = landscape(letter)
MARGIN = 0.5 * inch
BRAND = HexColor("#1F3864")
GREY = colors.HexColor("#888888")

These are stable value constants, not ReportLab's rendering API. The rendering API (Table, Flowable, canvas, BaseDocTemplate, …) is intentionally not re-exported — it's what the blocks encapsulate. If a report genuinely needs one, importing it from reportlab directly is the explicit, self-documenting escape hatch.

One palette for the whole report: Theme

A Theme bundles fonts and colours and produces every block's config from them. Pass it to Report and blocks are styled automatically; explicit configs and per-call overrides still win.

from pdfblox import Report, Theme, HexColor

theme = Theme(primary_color=HexColor("#7A0019"))  # brand colour

(
    Report("out.pdf",
           theme=theme,
           header_config=theme.header_config("Quarterly Report"),
           footer_config=theme.footer_config())
    .add_heading("Summary")          # styled from theme
    .add_paragraph("Body text.")     # styled from theme
    .add_callout("42", "Sensors")    # styled from theme
    .build()
)

Charts

pdfblox draws native vector charts with ReportLab's own graphics engine — no Plotly, kaleido, or matplotlib, and no extra dependency. Good for the standard reporting charts; series colours come from the active Theme.

from pdfblox import Report, get_theme

(
    Report("out.pdf", theme=get_theme("forest_green"))
    .add_bar_chart([[3, 5, 2], [4, 1, 6]], categories=["A", "B", "C"],
                   series_names=["Plan", "Actual"])
    .add_line_chart([1, 3, 2, 5], categories=["Q1", "Q2", "Q3", "Q4"])
    .add_pie_chart([30, 50, 20], labels=["North", "South", "East"], donut=True)
    .add_scatter_chart([(1, 2), (3, 4), (5, 3)])
    .build()
)

To embed a chart rendered elsewhere (e.g. a Plotly/server figure), render it to PNG/SVG bytes in the data-source layer and place it with make_image instead — pdfblox stays rendering-engine-free either way.

Built-in presets

Six ready-made palettes popular for reporting — corporate_blue, slate_gray, forest_green, burgundy, teal, graphite. Look one up by name (with optional overrides) or call its factory:

from pdfblox import Report, get_theme, available_themes

print(available_themes())               # list preset names
theme = get_theme("slate_gray", base_font_size=11)

Report("out.pdf", theme=theme,
       header_config=theme.header_config("Status Report"),
       footer_config=theme.footer_config()).add_heading("Summary").build()

Recommended entry point: the Report builder

from pdfblox import Report, HeaderConfig, FooterConfig

(
    Report("out.pdf",
           header_config=HeaderConfig(title="Status"),
           footer_config=FooterConfig())
    .add_heading("Summary")
    .add_paragraph("All systems nominal.")
    .add_divider()
    .add_callout("42", "Active Sensors")
    .add_keyvalue_table([("Site", "North"), ("Status", "OK")])
    .build()
)

Quick start

A paginated table report with a header and footer — no data source, just inline data:

from pdfblox import (
    ColumnConfig, PdfConfig, HeaderConfig, FooterConfig,
    build_paginated_pdf, letter, landscape, inch,
)

data = [
    {"name": "Sensor A", "value": 12.4, "status": "OK"},
    {"name": "Sensor B", "value": 99.1, "status": "ALERT"},
]

columns = [
    ColumnConfig("Instrument", 3 * inch, "name", alignment="LEFT"),
    ColumnConfig("Reading", 2 * inch, "value", formatter=lambda v: f"{v:.1f}"),
    ColumnConfig("Status", 2 * inch, "status"),
]

build_paginated_pdf(
    data,
    columns,
    "report.pdf",
    pdf_config=PdfConfig(page_size=landscape(letter)),
    header_config=HeaderConfig(title="Instrument Status", company_info=["Acme Co."]),
    footer_config=FooterConfig(),
)

For mixed content (charts, paragraphs, custom flowables) use build_pdf; for a grid of chart tiles use build_tile_grid to produce per-page Table flowables, then pass them to build_pdf. Add a cover page by passing a TitlePageConfig.

Tests

pip install -e ".[test]"
pytest

Each building block has a focused test under tests/ that exercises it and, where relevant, renders a real PDF into a temp directory.

License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pdfblox-1.4.0.tar.gz (49.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pdfblox-1.4.0-py3-none-any.whl (44.9 kB view details)

Uploaded Python 3

File details

Details for the file pdfblox-1.4.0.tar.gz.

File metadata

  • Download URL: pdfblox-1.4.0.tar.gz
  • Upload date:
  • Size: 49.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for pdfblox-1.4.0.tar.gz
Algorithm Hash digest
SHA256 d85d290fd7c2839d8b9a544d008a2d6f1f071251afd3281c52c512c669903aa3
MD5 88a637219c5a9cbbd2256c2aa89e2336
BLAKE2b-256 9af394fe1b7439cd5a9f417d3477183f2f44c1a070770b7dcf09de7615cba725

See more details on using hashes here.

File details

Details for the file pdfblox-1.4.0-py3-none-any.whl.

File metadata

  • Download URL: pdfblox-1.4.0-py3-none-any.whl
  • Upload date:
  • Size: 44.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for pdfblox-1.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2822c62dc70138d36654dbb85d53f80ba983d822fc645cb45d5de3178edc35e9
MD5 d0898157f11709fcd41663da14b1349c
BLAKE2b-256 0b859c274ef053323f7d89d4d75b36381392654f1072539cf0515eab03f06c7d

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page