mag-parse
One parse() for every document. PDFs go to mag-pdf;
everything else goes to mag-file-handler.
from mag_parse import parse
r = parse("invoice.pdf") # quality="fast" (default)
r = parse("report.pdf", quality="accurate") # table structure
r = parse("deck.pptx") # quality does not apply
r = parse(pdf_bytes, filename="report.pdf") # bytes work too
r.markdown # always populated
r.text # always populated
r.format # "pdf" | "docx" | "xlsx" | "eml" | ...
r.engine # which engine actually ran
r.ok, r.error, r.warnings
The facade itself has zero required dependencies. Both engines are extras, and that is not tidiness — see Install.
Routing
Decided by magic bytes, never the extension. A .docx renamed to .pdf
does not reach the PDF engine, and a PDF with no extension does.
parse(file, quality=...)
│
sniff %PDF
│
┌────┴─────┐
PDF not PDF
│ │
mag-pdf mag-file-handler
│ │
└────┬───────┘
▼
one Result
quality is a PDF-only knob
| What runs | Install | |
|---|---|---|
"fast" (default) |
LiteParse behind an OCR gate; OCRs only pages that need it | mag-parse[pdf] |
"accurate" |
DocLayout-YOLO + TableFormer for real table structure | mag-parse[tables] |
For every other format quality is accepted and ignored, so a caller never
has to branch on file type. Result.quality is "" there — the knob did not
default, it does not exist.
"accurate"selects mag-pdf'sprofile="tables", leavingtable_modeat its default. Those are two different fast/accurate axes: the profile picks the pipeline,table_modepicks TableFormer's weights. The heavier weights measured 27.6 s against 16.1 s for one additional table row, so they are not what "accurate" buys — the table pipeline is.
Markdown, and how honest it is
Both .markdown and .text are always populated, on every path including
failure. They are not equally structured, and structured_markdown says which
you got:
| Source | .markdown |
structured_markdown |
|---|---|---|
| real GFM — pipe tables, headings | True |
|
| md / txt / csv | the text, which is already faithful | False |
| docx / xlsx / pptx / html / eml | the text, tables flattened | False + a warning |
A docx table currently arrives as tab-separated fragments rather than a pipe
table. That is mag-file-handler's plain-text output passed through verbatim,
and the warning says so rather than letting it pass as structured markdown.
Teaching the engines real markdown per format is the planned follow-up; the
API does not change when it lands.
Errors
A bad document is a Result, never an exception — check .ok / .error.
Only two things raise, and both are the caller's to fix:
| Exception | Means |
|---|---|
UnknownQuality |
quality= was not "fast" or "accurate". Raised before any I/O, so a typo cannot run the wrong pipeline on a large file first. |
EngineNotAvailable |
The extra for this file type is not installed. Names the exact pip install. |
Result.status is "ok", "empty" or "error". empty is a failure — an
extraction that returns nothing while reporting success is the silent failure
both engines guard against, and the facade does not launder it.
Install
pip install 'mag-parse[pdf]' # PDFs; one dependency, Tesseract bundled
pip install 'mag-parse[office]' # docx, xlsx, pptx, eml, html, md, txt, csv
pip install 'mag-parse[all]' # both of the above
pip install 'mag-parse[tables]' # adds quality="accurate" (~2 GB: torch)
The engines are extras rather than dependencies because extractous (under
mag-file-handler) publishes no Linux ARM64 wheel and declares
requires-python <3.14, while liteparse (under mag-pdf) has neither
limit. Making the office side required would impose both constraints on
PDF-only users:
| Platform | [pdf] |
[office] |
|---|---|---|
| Linux x86-64 | ✅ | ✅ |
| Linux ARM64 | ✅ | ❌ no wheel |
| macOS ARM64 / x86-64 | ✅ | ✅ |
| Windows x86-64 | ✅ | ✅ |
| Python 3.14 | ✅ | ❌ <3.14 |
Python 3.10+. Apache-2.0.
Metadata
Release files for mag-parse 0.1.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 | |
|---|---|---|---|
| mag_parse-0.1.0.tar.gz | 16.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| mag_parse-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 29.1 kB
Release files / mag_parse-0.1.0.tar.gz
| Download URL | mag_parse-0.1.0.tar.gz |
|---|---|
| Size | 16.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4bc33889c69029b053d913dd0bae80ca875177dd028c4ce69c8109eae38129e5
|
|
BLAKE2b-256 checksum How to use checksums |
ca61fe008a24d5c849ec6807b82eef06e696ee4c399436f37d4389c10354f0db
|
| 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 17, 2026.
Transparency logRelease files / mag_parse-0.1.0-py3-none-any.whl
| Download URL | mag_parse-0.1.0-py3-none-any.whl |
|---|---|
| Size | 12.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
cc2cf5a66a7f80ed0e3cb0093456eef8f984952414db4b6cc2f76cc8e1036be5
|
|
BLAKE2b-256 checksum How to use checksums |
2fd965851810b84769ef466cc57f648a9a7504c0b3ff89d59293b4ad1bcc0f59
|
| 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 17, 2026.
Transparency log