paper-docx
A python-docx fork for creating and editing Word documents safely without changing your imports.
paper-docx is a fork of
python-docx for working with
Word documents. It keeps the docx import name and the python-docx object
model, so existing code works unchanged. It adds safe, structured editing of
documents you didn't author: search across fragmented text, tracked changes,
comments, comparison, and package-safe saves. When an edit cannot be made
safely, it raises a typed PaperRefusal and leaves the document unchanged.
import docx # the import name is unchanged
doc = docx.Document("contract.docx")vs python-docx
High-level changes relative to python-docx 1.2.0.
Guide
Targeting, guarded edits, protection, comparison, and saving in paper-docx.
API reference
The complete paper-docx 0.2.0 public API, including inherited python-docx APIs.
GitHub
Source, issues, and discussions.
PyPI
pip install paper-docx
Quick start
pip uninstall -y python-docx paper-docx
pip install paper-docx
paper-docx-doctor # verify the installCreate a Word redline from two document versions:
import tempfile, docx
from docx.package import compare
tmp = tempfile.mkdtemp()
a = docx.Document()
a.add_paragraph("Payment is due within thirty calendar days of the invoice date.")
a.save(f"{tmp}/v1.docx")
b = docx.Document()
b.add_paragraph("Payment is due within thirty business days of the invoice date.")
b.save(f"{tmp}/v2.docx")
result = compare(f"{tmp}/v1.docx", f"{tmp}/v2.docx", author="Reviewer")
[(r.revision_type, r.text) for r in result.document.revisions]
# [('deletion', 'calendar'), ('insertion', 'business')]
result.document.revisions.accept_all()
result.document.paragraphs[0].text
# 'Payment is due within thirty business days of the invoice date.'The redline is w:ins/w:del markup that Word renders as tracked changes.
Before returning, compare verifies on private copies that accepting the
result reproduces the revised document and rejecting it reproduces the
original. If a difference cannot be represented safely, compare raises a
typed error.
The everyday case, replacing a phrase Word has fragmented across runs:
from docx.search import find_one
find_one(doc, "within 30 days").replace(
"within 45 days", tracked=True, author="Reviewer",
)
[(r.revision_type, r.author, r.text) for r in doc.revisions]
# [('deletion', 'Reviewer', '30'), ('insertion', 'Reviewer', '45')]Compatibility
- PyPI distribution and GitHub repository:
paper-docx - Python import:
docx. Neverimport paper_docx. - Upstream compatibility version:
docx.__version__ == "1.2.0" - Fork version:
docx.__paper_version__
import docx raises ImportError when both distributions' metadata are
installed. Paper adds validation and guarded edits, so it can reject inputs
or operations that python-docx accepts.