paper-docx
vs python-docx
High-level changes relative to python-docx 1.2.0, and why.
paper-docx keeps python-docx 1.2.0's import name and object model, then adds guarded editing and package operations. Upstream's pytest and behave suites run alongside Paper's tests.
High-level changes
- Distribution safety. Renamed
paper-docx, import staysdocx.docx.__version__remains"1.2.0"anddocx.__paper_version__identifies the fork.import docxraisesImportErrorif both distributions are installed;paper-docx-doctorverifies the environment. - Package and save integrity. ZIP preflight on open, relationship
validation at load, staged path saves, and
patch_save/diff_package/diagnose. Multi-part mutations roll back on late failure, so a caught refusal leaves the document unchanged. - Finding and editing real text. Word fragments text across runs, so
matching on
paragraph.textmisses most phrases and assigning it destroys formatting.docx.storytraverses body, headers, footers, notes, and comments with revision views and blind-region counts.docx.searchmatches exact text across fragmentation;Span.replaceedits only the matched runs or emits a tracked change. - Reviewing changes.
Document.revisionsenumerates, accepts, and rejects tracked changes, including paired moves and row revisions, transactionally. Comment APIs manage native threads and resolution state. - Structured surfaces. Typed operations for content controls, comments, bookmarks, fields, numbering, merge-aware tables, hyperlinks, notes, and picture replacement — each refusing what it cannot do safely.
- Cross-document workflows.
compare()builds a verified redline and refuses differences it cannot represent.docx.compositioncopies formatted content between documents while reconciling styles, numbering, media, and bookmarks. - Compatibility boundaries.
compare()redlines text and table rows only; other difference types refuse. Traversal reports blind spots (math, embedded objects,altChunk, hidden text are counted, not read). Protection covers Paper mutators, not access control. Malformed packages and unsafe save destinations can refuse where python-docx would proceed.
At a glance
| Capability | python-docx | paper-docx |
|---|---|---|
| Create documents, paragraphs, tables, styles | ✅ | ✅ (inherited) |
| Find text across run fragmentation | — | docx.search |
| Replace text preserving untouched formatting | — | Span.replace |
Author tracked changes (w:ins/w:del) | — | Span.replace(tracked=True), docx.blocks |
| Enumerate / accept / reject revisions (incl. moves, rows) | — | Document.revisions |
| Traverse headers, footers, notes, comments, text boxes | partial, manual | docx.story, with blind-spot counts |
| Fill content controls by type | — | docx.controls |
| Comment threads: reply, resolve | add only | docx.commentops |
| Table edits by visual grid, merge-aware | raw XML indexes | docx.tableops |
| Create real list numbering | — | docx.numbering |
| Dependency-aware bookmarks | — | docx.bookmarks |
| Author fields (PAGE, REF, TOC) | — | docx.fields |
| Effective formatting with per-value sources | direct properties only | docx.formatting |
| Respect Restrict-Editing protection | — | mode-aware docx.protection |
| Validate malformed ZIP and OPC structures | — | on open and before delivery |
| Guarded path save | — | staged, validated replacement |
| Preserve unchanged package-part bytes | — | patch_save |
| Tracked-changes redline from two versions | — | compare(), verified both ways |
| Cross-document composition with reconciliation | — | docx.composition |
| Typed, catchable safe refusals | — | docx.errors, transactions |
| Install verification | — | paper-docx-doctor |