docx_plus¶
OOXML-level extensions for python-docx.
python-docx is an excellent library that stops at a well-defined
boundary. Past that boundary — the style cascade, content controls,
anchored comments, tracked changes, custom numbering, table borders —
the usual answer is a StackOverflow snippet that reaches into
element._p and builds raw lxml by hand. Everyone writing serious
document automation ends up with a private, half-tested pile of that
code.
docx_plus is that pile, done properly: typed, tested against documents
Word itself authored, and schema-strict about where elements are allowed
to go. It composes with python-docx rather than replacing it — you
keep your Document object and reach for docx_plus only where you
need to.
from docx import Document
from docx_plus.styles import resolve_effective_formatting
doc = Document("report.docx")
# "Why is this heading 13pt and blue?" — a question python-docx can't answer,
# because the value is inherited, not set on the paragraph at all.
resolved = resolve_effective_formatting(doc.paragraphs[0], include_provenance=True)
print(resolved.font_size) # 13.0
print(resolved.provenance["font_size"]) # FormattingSource(layer='paragraphStyle',
# style_id='Heading2', ...)
Requires Python 3.10+. The only dependencies are python-docx and
lxml. Current release: v0.6.2, published 2026-08-21 on
PyPI.
Start here¶
-
Install, your first script, and the seven conventions that apply across every module. Read this first.
-
One task-oriented page per capability — styles, forms, comments, tracked changes, tables, publishing, linting, and the rest.
-
Why the OOXML behaves the way it does, and why the library is shaped around it. The cascade, the parts model, the design commitments.
-
Every public symbol, plus per-module pages with full signatures and docstrings generated from source.
Driving the library from an LLM coding agent? Point it at the agent skill instead of hand-feeding it the API. Working from a shell or CI? See the CLI.
Capabilities¶
| Capability | Detail | Guide |
|---|---|---|
| Style cascade | Effective formatting for any paragraph / run / cell through the full eight-layer cascade, with per-field provenance. Create, modify, and remap styles; materialise any of 107 latent Word built-ins. | Styles |
| Content controls | Text / dropdown / date / checkbox controls via FormBuilder; round-trip read and write of values. |
Forms |
| Comments | Anchored comments with the body-side range markers python-docx skips, so "show in document" works. Threading — reply / resolve / reopen — plus durable ids and author presence. | Comments |
| Tracked changes | Mark runs as insertions / deletions, read revisions with author and timestamp, accept / reject, toggle track-changes mode. | Tracked changes |
| Fields | PAGE / NUMPAGES / DATE / STYLEREF and generic complex fields; mark fields dirty so Word recalculates on next open. |
Fields |
| Tables | Table / row / cell borders and shading, merge and unmerge, w:hMerge normalization, direct-formatting reads. Conditional <w:tblStylePr> branches resolve the way Word applies them. |
Tables |
| Numbering | Custom bullet and multi-level numbered list definitions, applied and restarted per paragraph. | Numbering |
| Layout | Multi-column sections, mid-document section breaks, distinct even/odd headers, line numbering, page borders. | Layout |
| Bookmarks | Paired body markers plus REF / PAGEREF cross-references. |
Bookmarks |
| Notes | Footnotes and endnotes over the separate footnotes.xml / endnotes.xml parts; insert and edit in place. |
Notes |
| Publishing | Table of Contents, figure / table captions via SEQ, Table of Figures. |
Publishing |
| Protection | Form-fill, read-only, comments-only, or tracked-changes enforcement at the document level. | Forms |
| Lint | Audit a document for direct formatting fighting the styles, skipped outline levels, hand-typed lists, and whitespace used as layout — then describe the repair as an ordered, serializable plan. Read-only throughout. | Linting |
| Command line | docx-plus inspect / restyle / controls / comments / lint / plan / skill over the library. |
CLI |
Project status¶
v0.6.2 — beta, and shipping. 2,101 tests, 96% coverage, mypy
--strict clean with zero ignores. CI runs Python 3.10–3.13 on Linux
plus a Windows job, and a lower-bound dependency job pinned to
python-docx==1.0.0 / lxml==4.9.0.
The API is stable in practice but pre-1.0: breaking changes are possible on minor versions and are called out in the changelog.
| Release | Shipped |
|---|---|
| v0.1.0 | Foundation (core/), style inspection / modification / remapping, content controls, fields, protection |
| v0.2.0 | Comments, layout, bookmarks, notes, core/parts; toggle properties, in-place edits, line numbering, page borders, conditional table styles, publishing/ |
| v0.3.0 | Tracked changes (revisions/) and the docx-plus CLI (inspect, restyle, controls) |
| v0.4.0 | Threaded comments over commentsExtended.xml, and docx-plus comments |
| v0.5.0 | Table formatting (tables/), custom numbering (numbering/), comment durable ids and author presence, the agent skill in the wheel behind docx-plus skill |
| v0.6.0 | The linter (lint/) — 20 rules, profiles, plan_fixes, and docx-plus lint / plan; the cascade resolver corrected against live Word; the document-wide sweep, stop_below baselines, read_fields |
ROADMAP.md
is the live record of what is shipped, backlogged, and deliberately
declined. On the backlog: content-control data binding to Custom XML
Parts, bibliography and BIBLIOGRAPHY fields, theme writing, glossary
placeholder text, and password-protected forms.
Contributing¶
See
CONTRIBUTING.md
for the development setup, quality gates, and conventions — including
the expectation that new OOXML output is verified against a file Word
itself authored.
Auditing the project? See the Test Gaps snapshot.