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.4.0.tar.gz (139.0 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.4.0-cp311-abi3-win_amd64.whl (10.5 MB view details)

Uploaded CPython 3.11+Windows x86-64

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

Uploaded CPython 3.11+manylinux: glibc 2.28+ ARM64

pptspine-0.4.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.4.0-cp311-abi3-macosx_11_0_arm64.whl (9.3 MB view details)

Uploaded CPython 3.11+macOS 11.0+ ARM64

pptspine-0.4.0-cp311-abi3-macosx_10_12_x86_64.whl (10.1 MB view details)

Uploaded CPython 3.11+macOS 10.12+ x86-64

File details

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

File metadata

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

File hashes

Hashes for pptspine-0.4.0.tar.gz
Algorithm Hash digest
SHA256 8c2d13b80cd1cc1e3da02dc73fccdf07da4cab3c714ea3e07c0ea5c168d567f1
MD5 7d4e58debad8c0c197d14a709fed2f61
BLAKE2b-256 51b5b46dd6fae47fa923981fefdcf9a0becdd9e3369d253c17680fc30dec6031

See more details on using hashes here.

File details

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

File metadata

  • Download URL: pptspine-0.4.0-cp311-abi3-win_amd64.whl
  • Upload date:
  • Size: 10.5 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.4.0-cp311-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 ea42bb22525ff75d4dd44c0f40475a756b3fef6b0afcd14739e2c22214541d3d
MD5 9f2d115f6c7fd3b121d79ff63d65c6fe
BLAKE2b-256 90e4dc76d6c3c561bca883f708800b994c4171bcea46efc4f3e0da68a5512ab7

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for pptspine-0.4.0-cp311-abi3-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 5d825e31ba7423cb32d2482d8547e29394a6dd779b50e08e5eb4827aeeb66294
MD5 f90a1f83351c76a11aa9bcf8de76c0af
BLAKE2b-256 68a282a1a2861d457f39b17ceadaa0f679f59e8038182b4741cb72b58d3fbecd

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for pptspine-0.4.0-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 84c387472c5da783c9091843459c8956d45cf4ad41e4b85212d0ce6ac5d9dcbd
MD5 625abb65c9feea4d8a833e9626d1850b
BLAKE2b-256 1c111663a8240fb2f989e7a4f94bbb3c32324582582be5cb2a14969e8f470c40

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for pptspine-0.4.0-cp311-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 58a89c9f022ae17ac618f57ac42fb7769cc3f8a35c31c712df63f5915a85b469
MD5 573e412bdf6420cca8da79a80b6cc495
BLAKE2b-256 d8b28184a853c1735ae7770f869e73a0a30ed10ecb0c466311799c060abc1dda

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for pptspine-0.4.0-cp311-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 0ef2b31de5eb876d2dea18d884b0c383196e14423661715e76da87ece0764610
MD5 94b8fa308c1c8069dabdce1a52bdd626
BLAKE2b-256 4b0e1752f39cbc8512d121b246519d40ef15545ecb4945fd0064c5cfac51b00d

See more details on using hashes here.

Release history Release notifications | RSS feed

0.5.1

6 files

0.5.0

6 files

This release

0.4.0 This release

6 files

0.3.0

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