Skip to main content

pptspine

PyPI

A pure-Rust PowerPoint (.pptx) parser with Python bindings (PyO3 / maturin, abi3-py311). A .pptx file is OOXML — a zip archive of XML parts — and pptspine walks that XML directly to produce a structured, information-preserving model: slides, text frames (paragraphs + styled runs), tables (cells, merges, fills), pictures, and autoshapes. A parsed deck can also be exported to PDF (to_pdf() / save_pdf(), one page per slide) through the shared pure-Rust pdf-typeset engine from the sibling pdfspine — no LibreOffice, no cloud converter. Embedded images can additionally be OCR'd locally, offline, and deterministically via the sibling ocrspine crate (PP-OCRv5 through tract-onnx — no cloud, no network).

Capabilities

Area Status
Slides + slide size parsed
Text frames: paragraphs, runs, text parsed
Run styling: font, size, bold, italic, solid-fill color parsed
Paragraph level + alignment parsed
Tables: rows, cells, cell text parsed
Table merges: gridSpan / rowSpan / hMerge / vMerge parsed
Cell solid-fill color parsed
Pictures: r:embed rel → media name; raw bytes via Presentation.image_bytes() parsed
Autoshapes: geometry name, fill, stroke, optional text parsed (best-effort)
Groups (p:grpSp): recursive parsed
Speaker notes (notesSlideSlide.notes) parsed
Structured export: to_text() / to_markdown() (GFM + HTML tables for merges) working
PDF export: to_pdf() / save_pdf() — one page per slide; placeholder/theme inheritance, shape transforms (rot/flip/adj/dash/srcRect), group affine, tables, slide backgrounds, body-anchor/autofit working
Image OCR (embedded pictures → words + boxes) working (ocr_image)
Image-table geometry reconstruction from OCR boxes deferred (stub)

Parsing is tolerant: unknown elements are skipped, missing attributes become None, and malformed input yields a typed PptError rather than a panic.

Install

pip install pptspine

pptspine is on PyPI. OCR works out of the box: the PP-OCRv5 weights ship in the shared ocrspine-models data package — a runtime dependency pip pulls in automatically — so the wheel itself ships no models. To build from source instead, see below.

Build (from the package root)

uv venv .venv
VIRTUAL_ENV="$(pwd)/.venv" uv pip install maturin pytest
# Structural parsing needs no models. The OCR path resolves models from
# ../ocrspine/models by default (or set OCRSPINE_MODELS).
OCRSPINE_MODELS="$(cd ../ocrspine && pwd)/models" \
  VIRTUAL_ENV="$(pwd)/.venv" .venv/bin/maturin develop --release

Use from Python

import pptspine

pres = pptspine.open("deck.pptx")
print(pres.slide_count, pres.slide_size)   # e.g. 2 (9144000, 6858000)  # EMU

for slide in pres.slides():
    for shape in slide.shapes():           # list[dict], introspectable
        if shape["kind"] == "text":
            for para in shape["paragraphs"]:
                for run in para["runs"]:
                    print(run["text"], run["bold"], run["color"])
        elif shape["kind"] == "table":
            for row in shape["rows"]:
                print([cell["text"] for cell in row])
        elif shape["kind"] == "picture":
            print("image:", shape["media"])

# Structured export + speaker notes:
print(pres.to_text())          # slides joined by "--- slide N ---"
print(pres.to_markdown())      # one section per slide; GFM / HTML tables
print(pres.slides()[0].text)   # all text on a slide (convenience)
print(pres.slides()[0].notes)  # speaker notes, or None

# Run OCR on raw image bytes (PNG/JPEG), offline:
items = pptspine.ocr_image(open("scan.png", "rb").read())
print(" ".join(i["text"] for i in items))

# End-to-end: pull an embedded image's bytes and OCR them, offline:
for shape in pres.slides()[0].shapes():
    if shape["kind"] == "picture" and shape["media"]:
        data = pres.image_bytes(shape["media"])   # bytes | None
        if data:
            print([i["text"] for i in pptspine.ocr_image(data)])

Export to PDF

pres = pptspine.open("deck.pptx")
pres.save_pdf("deck.pdf")          # one PDF page per slide
pdf_bytes = pres.to_pdf()          # or in-memory bytes

# Optional: map a requested font family to a local font file (or to another
# installed family), layered on top of the built-in substitution table:
pres.save_pdf("deck.pdf", font_map={"Aptos": "/path/to/Aptos.ttf"})

Rendering is deterministic and fully offline. Missing fonts degrade gracefully: an available face is substituted and a Python UserWarning is emitted once per warning kind — the export never fails on a missing font.

Rust workspace

crates/
  ppt-core    domain model + geometry (EMU) + typed PptError. No IO/zip/XML.
  ppt-parse   OOXML reader: zip extract + quick-xml walk -> Presentation.
  ppt-ocr     image-OCR bridge over ocrspine (PaddleOcr).
  ppt-render  slide -> PDF renderer over the shared pdf-typeset engine (from pdfspine).
  py-bindings PyO3 _core extension (the FFI chokepoint).

Deferred / follow-up

  • Image-table geometry reconstruction from OCR boxes (ppt_ocr::reconstruct_table_from_image, currently a typed Unsupported stub).
  • Richer color models (gradients), hyperlinks, charts, SmartArt, comments.

Download files

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

Source Distribution

pptspine-0.3.0.tar.gz (135.1 kB view details)

Uploaded Source

Built Distributions

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

pptspine-0.3.0-cp311-abi3-win_amd64.whl (10.4 MB view details)

Uploaded CPython 3.11+Windows x86-64

pptspine-0.3.0-cp311-abi3-manylinux_2_28_aarch64.whl (9.5 MB view details)

Uploaded CPython 3.11+manylinux: glibc 2.28+ ARM64

pptspine-0.3.0-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (10.5 MB view details)

Uploaded CPython 3.11+manylinux: glibc 2.17+ x86-64

pptspine-0.3.0-cp311-abi3-macosx_11_0_arm64.whl (9.3 MB view details)

Uploaded CPython 3.11+macOS 11.0+ ARM64

pptspine-0.3.0-cp311-abi3-macosx_10_12_x86_64.whl (10.9 MB view details)

Uploaded CPython 3.11+macOS 10.12+ x86-64

File details

Details for the file pptspine-0.3.0.tar.gz.

File metadata

  • Download URL: pptspine-0.3.0.tar.gz
  • Upload date:
  • Size: 135.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pptspine-0.3.0.tar.gz
Algorithm Hash digest
SHA256 77bc98f2825c9104ecbb49855e9806577614ad6d123d394676f9017291a45969
MD5 51237b45e90176bbbb0119b0c5e86d64
BLAKE2b-256 34ef551c041f37d5881e406b3ebab1b62aea2234ef3f2ca00611a6163f66b228

See more details on using hashes here.

File details

Details for the file pptspine-0.3.0-cp311-abi3-win_amd64.whl.

File metadata

  • Download URL: pptspine-0.3.0-cp311-abi3-win_amd64.whl
  • Upload date:
  • Size: 10.4 MB
  • Tags: CPython 3.11+, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pptspine-0.3.0-cp311-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 7a808a4e870f83a50524261e624d22f92d1acd8e9e820f92628b398000dd7cdf
MD5 be6eb05faf85bb2316b80189146ac5f2
BLAKE2b-256 b975577bd9c1264b857ed27ec7ede94e6eea60bcd17e8916af2ff2937a214998

See more details on using hashes here.

File details

Details for the file pptspine-0.3.0-cp311-abi3-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for pptspine-0.3.0-cp311-abi3-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 016b319d8046eccfd8ec7f19551e02ff22bf07c215bd46ef3ffe53724179121f
MD5 a4332dc6286cad1c27c30a714ddfac5b
BLAKE2b-256 672355c0a69d110a9b18d6bd7440db692bc5a7d8afa50f6082505870d2b74a29

See more details on using hashes here.

File details

Details for the file pptspine-0.3.0-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for pptspine-0.3.0-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 a3aecb5d0d8d793719cb11f1b69612eac8ceaff3d21aeab965778bd83a6ddf45
MD5 a1deb18ab77d7a4fa4e8a94ff94e8ab3
BLAKE2b-256 f2ed7066374db410235d0c78850fb691c15dec3a4e7cafd263385e87b9978ad2

See more details on using hashes here.

File details

Details for the file pptspine-0.3.0-cp311-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for pptspine-0.3.0-cp311-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 f478a9de3bd52000bb3579c3d22950109bde54889d96d9cde02535ad087b3c7e
MD5 c99a681404324e33c14c3d713a609325
BLAKE2b-256 df501b75d275ff47efbde554c406cd46c8cf99cf512a6471e32ffc52b19d99b6

See more details on using hashes here.

File details

Details for the file pptspine-0.3.0-cp311-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for pptspine-0.3.0-cp311-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 205ba87ea4105751ef91f37c376ac40a95483e3e65ff812e1e5b80a355d6480b
MD5 673e7c7d47701ec11d2442cb07d36ab8
BLAKE2b-256 cb595c398da086564daf7a2fac806476faf12779d702b8ecc0fc4225c9de057a

See more details on using hashes here.

Release history Release notifications | RSS feed

0.5.1

6 files

0.5.0

6 files

0.4.0

6 files

This release

0.3.0 This release

6 files

0.2.0

6 files

0.1.1

6 files

0.1.0

5 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