Skip to main content

reportlab_layout

CI PyPI Python License MIT

PDF generation made easier, on top of reportlab and platypus. A cursor that moves down the page, with the reportlab canvas still at hand to draw exactly where you want on the page.

pip install reportlab_layout
from reportlab_layout import PDFMaker

with PDFMaker("report.pdf", top=25, auto_page_break=True) as doc:
    doc.set_footer(doc.make_paragraph("Acme Ltd", "Right"))
    doc.draw_paragraph("Third-term report", "Heading1 Centered")
    doc.draw_centered_line(wscale=0.4)
    doc.add_space()
    doc.draw_table([["Subject", "Mark"], ["Mathematics", "17"]])

    # And right there, without switching tool or file:
    doc.draw_round_rect(doc.x_left, doc.cursor_y - 40, doc.content_width, 40, radius=6, fill="#eef4fb")
    doc.draw_string("Distinction", *doc.cursor_point, halign="left", valign="cap")

The problem it solves

reportlab gives you two ways to work, and they do not mix well.

The canvas draws wherever you tell it, in points, from the bottom-left corner. Precise, but you hold the current position yourself, you recompute heights by hand, and one line inserted in the middle shifts everything after it.

Platypus threads flowables through frames and handles flow, pagination and table splitting. But it takes over the page: to draw a box behind a paragraph at an exact point you have to go through a BaseDocTemplate's onPage callbacks, which means writing the layout in two separate places and out of order.

This package keeps platypus flowables but lays them down itself, at the position of a cursor you can read, move and question at any time. The canvas stays reachable through doc.canvas. The two modes mix line by line.

doc.draw_paragraph("This paragraph moves the cursor down.")  # flow
y = doc.cursor_y                                             # current position
doc.draw_rect(doc.x_left, y - 30, doc.content_width, 30)     # absolute
doc.advance(30)                                              # the cursor follows

What it brings

  • An explicit cursor. doc.cursor.depth, doc.cursor_y, doc.remaining_height, doc.advance(h). No magic: you always know where you are on the page.
  • One method for plain text. draw_string(text, x, y, halign=…, valign=…, scale=…, angle=…) replaces the half-dozen variants everyone ends up writing, and the vertical centring is right — including the cap anchor that centres short labels on their capitals, which is what a table cell or a badge actually wants. See middle or cap?
  • One uniform return. Every drawing call returns a Box(x, y, width, height) that unpacks as a plain 4-tuple. You know what you just laid down, and where.
  • The two coordinate systems kept apart. The canvas ordinate goes up, the cursor depth goes down; PageGeometry is the only place that converts.
  • Nothing leaks. Every drawing is wrapped in saveState/restoreState, so a colour or a line width never contaminates the next call.
  • Two dependencies, reportlab and Pillow. No headless browser, no LaTeX, no system binary.

How it compares

The landscape

Tool Model System deps Licence Status (August 2026)
reportlab canvas absolute, points no BSD 5.0.1, very active
reportlab platypus flow, flowables no BSD same
reportlab_layout cursor + canvas no MIT this package
fpdf2 native cursor no LGPL-3.0 2.8.8, very active
pdfino platypus wrapper no MIT 0.1.0, 2023
pdfdocument platypus wrapper no BSD 4.0.0, 2020
borb object model no AGPL-3.0 3.0.9, active
WeasyPrint HTML + CSS no BSD 69.0, very active
pdfme document as a dict no MIT 0.5.0
rst2pdf reStructuredText no MIT 0.105, active
pypdf / pikepdf manipulation, not generation no BSD / MPL active
pylatex, Typst, wkhtmltopdf markup + external engine yes various various

What the community already offers

reportlab platypus is an excellent package, and it does far more than this one: tables split across pages, KeepTogether, tables of contents, bookmarks, multi-frame templates. If your document is a report that flows from start to finish, use platypus: this package has nothing to add. The difference comes down to one point: as soon as you need to alternate free drawing and flow in the same gesture, platypus makes you separate the content (the story) from the decoration (the onPage callbacks). Here, everything is written in the order it is drawn.

fpdf2 is the fairest comparison, because it is already a cursor model — set_xy, cell, multi_cell, ln() — and it is excellent: an HTML subset, tables, digital signing, a lively community. Three concrete differences. Its licence is LGPL-3.0, which is enough to rule it out in some settings; reportlab is BSD and this package MIT. Its rich-text engine is an HTML subset, where reportlab's Paragraph takes proper markup (<super>, <font>, subscripts, bullets) and knows how to wrap within a given width. And its cursor is the API: you cannot lay a reportlab flowable in the middle of it. If you are starting from scratch and the LGPL does not bother you, fpdf2 is a very good choice.

pdfino and pdfdocument sit in exactly the same slot: a sequential layer on top of platypus. They are older and simpler — h1(), p(), table() — and pdfino even lets you insert a raw flowable. What neither offers: reading and moving the cursor explicitly, absolute placement in points within the same API, corrected font metrics, and a Box returned from every call. They publish a document; this one lets you build a page. Worth noting too: pdfdocument has not released since 2020, and pdfino is at a 0.1.0 from 2023.

borb offers a complete object model and reads existing PDFs as well. It is more ambitious; it is also AGPL-3.0, a licence that reaches any service exposing it over a network. Rule it out up front in a proprietary setting.

WeasyPrint produces the finest typography of the list and handles paged CSS (@page, running headers, breaks). The price: you have to express the layout in HTML and CSS, and rendering goes through a full layout engine. For a document whose geometry is computed — a yearly planner, a slot table, a grid of photos — describing coordinates in CSS is a detour. For an invoice or a report whose template you already have on the web, WeasyPrint wins hands down.

pdfme, rst2pdf and pylatex share one stance: describe the document in some format (a dict, reStructuredText, LaTeX) and let an engine typeset it. Excellent when the content is the subject; unsuited when the coordinates are. pylatex and Typst add a heavy system dependency on top.

pypdf and pikepdf do not generate documents: they merge, split and sign. Complementary, not competing.

In short

What you need Prefer
A report that flows on its own, tables split across pages, a table of contents reportlab platypus
The template already exists in HTML/CSS WeasyPrint
A simple cursor, without reportlab, and the LGPL is no problem fpdf2
To publish a simple document in a handful of calls pdfino
To split, merge or sign existing PDFs pypdf, pikepdf
The content is marked-up text rst2pdf, pylatex
A page whose geometry is computed, alternating flow and point-exact drawing reportlab_layout

This package fills a narrow slot, but one that turns out to come up often: documents where you know the formula that gives each element's position — planners, grids, calendars, slot tables, contact sheets, mail merges — and where you still want to write text as it comes, without counting points by hand.

Going further

Compatibility

Python 3.11 to 3.14, reportlab 4.x and 5.x. The continuous-integration matrix covers each of these eight combinations.

Licence

MIT. reportlab is under a BSD licence, Pillow under MIT-CMU.

Release files for reportlab-layout 1.0.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 reportlab-layout 1.0.1
File Size Uploaded
reportlab_layout-1.0.1.tar.gz 69.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for reportlab-layout 1.0.1
File Interpreter ABI Platform
reportlab_layout-1.0.1-py3-none-any.whl Python 3 none any Details

Total release size: 95.4 kB

Release files / reportlab_layout-1.0.1.tar.gz

Download URL reportlab_layout-1.0.1.tar.gz
Size 69.1 kB
Tags Source
SHA-256 checksum
How to use checksums
ba13ea406d62a0bbc2e956abfa9ed295acaf648408aa0e578ca20dba30d9390a
BLAKE2b-256 checksum
How to use checksums
ebbd8acffec61cc34eaa2d69abddeffc2e975ecfaf57cb9e85263c8284ca3fa8
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 Aug 25, 2026.

Transparency log

Release files / reportlab_layout-1.0.1-py3-none-any.whl

Download URL reportlab_layout-1.0.1-py3-none-any.whl
Size 26.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ac8a8405e9ada492a2955822ca98f6b62957f90380ae8da3b849547eeff8d81c
BLAKE2b-256 checksum
How to use checksums
800ccc28be8f59854d80c8142e4953e89afebdf7dbf9b351954e1e27ff1a7068
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 Aug 25, 2026.

Transparency log

Release history Release notifications | RSS feed

1.6.0

2 release files

1.5.0

2 release files

1.4.0

2 release files

1.3.0

2 release files

1.2.0

2 release files

1.1.0

2 release files

1.0.2

2 release files

This release

1.0.1 This release

2 release files

1.0.0

2 release files

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