Skip to main content

paper-pptx

paper-pptx is an agent-first Python library for safely inspecting, editing, and composing existing PowerPoint (.pptx) files. It is a strict-superset hard fork of python-pptx v1.0.2 and a drop-in replacement. The distribution is renamed; the import name stays pptx, so existing code keeps working unchanged.

from pptx import Presentation          # unchanged — every existing snippet still runs

Why it exists

python-pptx is excellent at building a presentation from scratch. Its lossless package layer, disciplined XML mapping, and decade of absorbed edge cases are why this fork builds on it.

The harder problem is changing a live, branded, template-driven deck without breaking the relationships and inheritance that control how it renders. Hand-edited XML can produce silent corruption: a file that opens fine and is quietly wrong. An agent cannot eyeball the result, so it needs the deck's structure and every edit outcome as typed, machine-readable data. It also needs the library to refuse rather than guess.

What it adds

Everything below is additive API alongside the existing python-pptx API.

  • Perceive. Resolve the size, font, color, and emphasis a shape actually renders at through the placeholder → layout → master → theme chain, where stock python-pptx returns None. Each value includes its provenance (run.effective_font()). Emit the deck's text or structure as deterministic, versioned JSON for diffing and automation (inspect_text, inspect_deck).
  • Edit. Replace text without losing run formatting, addressed by a content-hash anchor so stale edits are detected rather than misapplied (pptx.edit). Copy, delete, move, and reorder slides and shapes; insert and delete table rows and columns. Author real bullets and numbering, normalize autofit, swap an image while keeping its position and crop byte-exact, and replace chart data by shape name after full validation. pptx.package.patch_save keeps every semantically unchanged part byte-identical.
  • Compose. Import slides under an explicit reconciliation mode: adopt the destination theme, keep the source appearance, or bake effective values in place (import_slide, append_deck). Rebind layouts (rebind_layout), apply real slide-number and date fields (apply_footers), and strip notes, comments, metadata, and unused parts before sending (scrub).
  • Verify. Diff two decks part-by-part, including slides added, removed, or moved and the text, chart, image, and notes changes within them (pptx.diff.diff_decks). The result identifies every changed part.

Safety contract

Every added operation either does exactly what it claims or refuses atomically. Mutating operations validate fully before they change anything. If an operation cannot proceed safely, it raises a typed PaperRefusal from pptx.errors and leaves the document byte-for-byte unchanged in memory and on disk. Callers can catch PaperRefusal separately from programmer errors, which remain plain ValueError or TypeError.

Package intake rejects duplicate, noncanonical, encrypted, unsupported, or resource-exhausting ZIP members before parsing XML. Saving to a filesystem path writes a sibling temporary package and atomically replaces the destination only after the ZIP is complete, preserving an existing destination's permission bits.

Example

Import a slide from one deck into another, then confirm the change with an independent diff:

from pptx import Presentation
from pptx.diff import diff_decks

deck = Presentation("house_deck.pptx")
source = Presentation("sector_team_deck.pptx")

# Import one slide, rebinding it to the destination theme. The report names every
# text run whose resolved appearance changed.
report = deck.import_slide(source, 0, mode="adopt_theme")
for shift in report.run_shifts:
    print(shift.text, shift.before["name"]["value"], "->", shift.after["name"]["value"])

deck.apply_footers(footer="Confidential", slide_number=True)  # real fields, not static text
deck.scrub(metadata=True, comments=True)                      # remove metadata and comments
deck.save("house_deck.v2.pptx")

# Compare the saved deck with the input using an independent diff.
delta = diff_decks("house_deck.pptx", "house_deck.v2.pptx")
print("slides added:", [s.slide_id for s in delta.slides_added])

Drop-in and name map

Only the distribution and repository are renamed. The importable package is pptx forever. This is the same distribution/import split as Pillow (pip install pillow, import PIL), and it preserves the millions of existing snippets and model priors that use from pptx import Presentation.

  • GitHub repository / PyPI distribution: paper-pptx
  • Python import: pptx
  • Fork sentinel: pptx.__paper_version__ = "0.1.1"
  • Upstream base: python-pptx v1.0.2 (git tag paper-base)

New upstream releases are merged, never rebased, so the fork retains its history and compatibility.

Installation

Install from PyPI:

pip install paper-pptx

paper-pptx and python-pptx both install the pptx import package and cannot safely coexist. Replace an upstream installation explicitly:

pip uninstall -y python-pptx paper-pptx
pip install paper-pptx

Verify the install:

paper-pptx-doctor

Documentation

Full documentation is under docs/. Start with the paper-pptx additions guide for an overview. Each added module has an API reference page under docs/api/. The remaining documentation is inherited from python-pptx and covers the shared foundation.

How it's tested

  • Upstream's pytest and behave suites run on every change to check compatibility with existing behavior.
  • A frozen, hash-pinned fixture corpus includes self-generated decks and LibreOffice round-trips with hash-pinned provenance sidecars. PowerPoint- and Google-authored fixtures are still pending.
  • The contract harness saves and reopens before asserting, enforces an exact changed-part budget and refusal atomicity, and validates selected paragraph, text-body, and table fragments against their schemas. Release verification installs LibreOffice and requires its load smoke.

License

MIT, inherited from python-pptx. Original work © Steve Canny and the python-pptx contributors; fork additions © Paper Instruments, Inc. See LICENSE.

Release files for paper-pptx 0.1.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 paper-pptx 0.1.1
File Size Uploaded
paper_pptx-0.1.1.tar.gz 10.8 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for paper-pptx 0.1.1
File Interpreter ABI Platform
paper_pptx-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 11.4 MB

Release files / paper_pptx-0.1.1.tar.gz

Download URL paper_pptx-0.1.1.tar.gz
Size 10.8 MB
Tags Source
SHA-256 checksum
How to use checksums
37b2defc48c979dafa05e541f6ca20b5647bbd88e58b60c18c8f762f956c4933
BLAKE2b-256 checksum
How to use checksums
266a45180e7a539202f3ff639e205d6c42fa0ca68b2b36e49aa7dc10e912f009
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

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 Jul 11, 2026.

Transparency log

Release files / paper_pptx-0.1.1-py3-none-any.whl

Download URL paper_pptx-0.1.1-py3-none-any.whl
Size 575.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5243b0edee833fe9e0024193afae31b9dfdf8ae9e3000ab9f20fa1b67ac97392
BLAKE2b-256 checksum
How to use checksums
c16aec4a3a8ddc6df572add9d90a6c935787828fea97725c02afdee562b31d9d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

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 Jul 11, 2026.

Transparency log

Release history Release notifications | RSS feed

0.2.0

2 release files

0.1.2

2 release files

This release

0.1.1 This release

2 release files

0.1.0

2 release files

0.0.1

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