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.

Installation

pip install pdfblox

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
Drawing (bespoke vector art) pdfblox.drawing DrawingConfig, vector_drawing + shapes (Circle, Ellipse, Polygon, Line, Path, …)
Overlays (anchored / page placement) pdfblox.overlay Overlay, watermark, text_drawing
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()

Drawing (bespoke vector art)

When a report needs a custom mark the other blocks don't cover — an emblem, logo, badge, or decorative shape — vector_drawing wraps ReportLab graphics shapes into a placeable Drawing flowable. The shape vocabulary is re-exported, so there's still no direct import reportlab:

from pdfblox import Report, vector_drawing, DrawingConfig, Circle, Polygon, HexColor

emblem = vector_drawing(
    [Circle(20, 20, 18, fillColor=HexColor("#F4C20D"), strokeColor=None),
     Polygon(points=[36, 22, 50, 20, 36, 16], fillColor=HexColor("#E8740C"))],
    DrawingConfig(width=52, height=40),
)

Report("out.pdf").add_heading("Brand").add_drawing(emblem).build()

shapes may also be a build(width, height) -> shapes callable when geometry depends on the drawing size. For data-driven vectors use the chart blocks above; for a finely detailed or photographic logo, prefer make_image.

Overlays (watermarks, emblems, page stamps)

Blocks place content in the flow — top-to-bottom in reading order. An overlay pins the same vector Drawing to a fixed spot on chosen pages, on top of the content: watermarks, corner emblems, "CONFIDENTIAL" stamps. Placement is anchor-first ("top-left""center""bottom-right"), with raw xy=(x, y) as an escape hatch; pages selects "all", "first", "last", an int/list of page numbers, or a callable(page, total).

from pdfblox import Report, watermark, vector_drawing, DrawingConfig, Circle, HexColor

emblem = vector_drawing([Circle(20, 20, 18, fillColor=HexColor("#F4C20D"))],
                        DrawingConfig(width=40, height=40))

(
    Report("out.pdf")
    .add_heading("Quarterly Report")
    .add_paragraph("…")
    .add_watermark("DRAFT")                                  # faint, 45°, every page
    .add_overlay(emblem, anchor="top-right", pages="first")  # emblem on page 1
    .build()
)

Same Drawing, two placement models — pick by where it belongs:

You want… Use
A drawing in the content stream (reading order, flows, page-breaks) add_drawing (flow)
A drawing pinned to the page (watermark, corner mark, stamp; may repeat) add_overlay

Overlays render on top with optional opacity (the watermark look) and rotation. Page numbers are absolute — a cover/title page counts as page 1.

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.

License

Licensed under the MIT 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.6.1.tar.gz (59.4 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.6.1-py3-none-any.whl (52.5 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for pdfblox-1.6.1.tar.gz
Algorithm Hash digest
SHA256 6967d95b51fd4c9c5ec4ee608a2496839626287e5a1c7d03dd310f057d0538be
MD5 6a64c19757fb71522c14b03b1cf373de
BLAKE2b-256 e08aff9cb0c63a810dcc17df0d477296c746d7ee5b07c95e525a553790bb7019

See more details on using hashes here.

File details

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

File metadata

  • Download URL: pdfblox-1.6.1-py3-none-any.whl
  • Upload date:
  • Size: 52.5 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.6.1-py3-none-any.whl
Algorithm Hash digest
SHA256 a12457774bbb7a1188cec2e41ef61b84a0fe1060368ab9eec074ca968a4319cf
MD5 d8fecae261bc067563a904e21c36e29c
BLAKE2b-256 4561a0ce9f5ed61f2144c5e43e33576db2bbbdfb9acdadd4e21ced22ed02824c

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