Python report generation — CSV, XLSX, and PDF with Rust performance. ⚡
Documentation · PyPI · Issues
- 🚀 High Performance — 100% streaming pipeline. CSV and XLSX use < 1 MB of RAM with 500K+ rows.
- 🦀 Powered by Rust — XLSX via
rustpy-xlsxwriter, JSON viaorjson. - 📄 3 Formats — CSV, XLSX, and PDF with a single API.
- 🔌 Pluggable — Supports
list[dict], JSON, SQL, or any custom source. - 🎯 Declarative Types — Automatic coercion for
int,float,bool,date,datetime. - 🪶 Lightweight — 3 runtime dependencies. No pandas, no numpy.
pip install pyrepsfrom pyreps import ColumnSpec, ReportSpec, generate_report
# data sample
data = [
{"id": 1, "customer": {"name": "Ana"}, "total": 100.50},
{"id": 2, "customer": {"name": "Bruno"}, "total": 250.00},
]
spec = ReportSpec(
output_format="csv", # or "xlsx" or "pdf"
columns=[
ColumnSpec(label="ID", source="id", type="int", required=True),
ColumnSpec(label="Customer", source="customer.name"),
ColumnSpec(label="Total", source="total", type="float",
formatter=lambda v: f"$ {v:.2f}"),
],
)
path = generate_report(data_source=data, spec=spec, destination="sales.csv")| Format | Renderer | Engine | Streaming |
|---|---|---|---|
| CSV | CsvRenderer |
csv stdlib (C) |
✅ Constant memory |
| XLSX | XlsxRenderer |
rustpy-xlsxwriter (Rust) |
✅ Constant memory |
PdfRenderer |
reportlab (C) |
| Source | Adapter | Detection |
|---|---|---|
list[dict] / generator |
ListDictAdapter |
Automatic |
| JSON string / bytes | JsonAdapter |
Automatic |
dict / Mapping |
JsonAdapter |
Automatic |
| SQL query | SqlAdapter |
Explicit |
| Custom | Implement InputAdapter |
Explicit |
ColumnSpec(label="Created", source="created_at", type="date")
ColumnSpec(label="Active", source="active", type="bool") # "yes" → True
ColumnSpec(label="Total", source="total", type="float") # "3.14" → 3.14Types: str, int, float, bool, date, datetime. Optional — type=None maintains pass-through.
spec = ReportSpec(
output_format="xlsx",
columns=[...],
metadata={
"xlsx": {
"width_mode": "auto", # "manual" | "auto" | "mixed"
"sheet_name": "Sales",
"columns": {
"ID": {"width": 8.0},
"Description": {"min_width": 20.0, "max_width": 50.0},
},
}
},
)from pyreps import SqlAdapter
generate_report(
data_source=None,
spec=spec,
destination="sales.csv",
input_adapter=SqlAdapter(
query="SELECT id, name, total FROM sales",
connection=connection,
),
)Benchmark with 6 columns and declarative types:
| Format | 500K rows | Peak RAM | rows/s |
|---|---|---|---|
| CSV | 2.39s | 51.11 MB | ~209K |
| XLSX | 4.37s | 51.11 MB | ~114K |
Memory usage remains stable (approx. 51MB process baseline) regardless of volume due to the 100% streaming pipeline.
📖 Complete documentation at JhonatanRian.github.io/pyreps
MIT