docx_plus.core.parts¶
Package part / relationship plumbing for separate OOXML parts. v0.2
capabilities (comments/, notes/) live in their own parts under
/word/comments.xml, /word/footnotes.xml, and /word/endnotes.xml,
each of which may be absent from a fresh document. get_or_create_part
is the single entry point that returns the part and its parsed XML root,
fabricating both if missing.
Internal XmlPart subclasses for footnote and endnote content types are
registered with PartFactory.part_type_for at import time so existing
documents round-trip with parsed .element rather than raw blobs.
Architecture walkthrough: ARCHITECTURE.md §7.5.
docx_plus.core.parts ¶
Package part / relationship helpers for separate OOXML parts.
v0.1 capabilities (styles, fields, controls, protection) mutated only the
main document part and settings.xml — both already present in every
docx. v0.2 introduces capabilities backed by separate OOXML parts that
may not exist in a fresh document:
/word/comments.xml(relationship :data:RT.COMMENTS)/word/footnotes.xml(relationship :data:RT.FOOTNOTES)/word/endnotes.xml(relationship :data:RT.ENDNOTES)
This module provides a single :func:get_or_create_part helper that the
comments and notes packages use to look up an existing part or
fabricate a fresh one with an empty default root.
python-docx already registers CommentsPart with
PartFactory.part_type_for[CT.WML_COMMENTS] so existing comments parts
deserialize with a parsed .element. It does not register
footnote / endnote part classes, so this module installs minimal
:class:~docx.opc.part.XmlPart subclasses for those content types at
import time. Without that registration a round-tripped document with
existing footnotes would surface them as raw blobs.
SPEC §2 lists the part / relationship plumbing as a v0.2 responsibility.
COMMENTS_SPEC
module-attribute
¶
COMMENTS_SPEC = PartSpec(
partname="/word/comments.xml",
content_type=WML_COMMENTS,
relationship_type=COMMENTS,
root_xml=_empty_root("comments"),
)
FOOTNOTES_SPEC
module-attribute
¶
FOOTNOTES_SPEC = PartSpec(
partname="/word/footnotes.xml",
content_type=WML_FOOTNOTES,
relationship_type=FOOTNOTES,
root_xml=_notes_root_with_separators("footnotes", "footnote", "separator"),
)
ENDNOTES_SPEC
module-attribute
¶
ENDNOTES_SPEC = PartSpec(
partname="/word/endnotes.xml",
content_type=WML_ENDNOTES,
relationship_type=ENDNOTES,
root_xml=_notes_root_with_separators("endnotes", "endnote", "separator"),
)
PartSpec
dataclass
¶
Identification for an OOXML part looked up or fabricated as a unit.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
partname
|
str
|
Absolute package URI, e.g. |
required |
content_type
|
str
|
Content-type URI from
:class: |
required |
relationship_type
|
str
|
Relationship-type URI from
:class: |
required |
root_xml
|
bytes
|
Complete XML bytes for a fresh, empty root element of this part (used only when creating a part that doesn't exist). |
required |
get_or_create_part ¶
Return (part, root_element) for the part identified by spec.
If the main document part already has a relationship of
spec.relationship_type, returns the related part. Otherwise
creates a fresh part with the empty default root from spec.root_xml
and wires the relationship from the document part. Idempotent — a
second call with the same spec returns the same part.
The part class is looked up in :attr:PartFactory.part_type_for so
callers get the most specific class registered for the content type
(CommentsPart for comments; the internal
:class:_FootnotesPart / :class:_EndnotesPart for the note parts).
Unknown content types fall back to :class:XmlPart.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
doc
|
Document
|
The python-docx :class: |
required |
spec
|
PartSpec
|
Identifier for the target part. Use :data: |
required |
Returns:
| Type | Description |
|---|---|
XmlPart
|
A tuple |
_Element
|
|