docx_plus.comments.anchor¶
Anchor a comment to a run, paragraph, or run range — and undo the same.
Writes the three body-side OOXML elements python-docx skips
(w:commentRangeStart, w:commentRangeEnd, the CommentReference
marker run) plus the comment body in comments.xml (created on first
use). delete_comment is the inverse and idempotent.
Architecture walkthrough: ARCHITECTURE.md §7.6.
docx_plus.comments.anchor ¶
Anchor and remove comments — the body-side OOXML python-docx skips.
python-docx 1.x writes <w:comment> into comments.xml but
omits the three body-side elements that anchor a comment to a text
range — w:commentRangeStart, w:commentRangeEnd, and the
CommentReference marker run. As a result, comments added via
python-docx show up in the review pane but have nothing in the
document text to point at. This module fills that gap.
:func:add_comment wraps a run, paragraph, or run-range with the three
body markers and appends a matching w:comment body to
comments.xml (the comments part is created on first use).
:func:delete_comment removes everything :func:add_comment wrote.
This module imports only from docx_plus.core and the sibling
docx_plus.comments.registry (SPEC §9.1).
CommentRef
dataclass
¶
Handle for an inserted comment.
Attributes:
| Name | Type | Description |
|---|---|---|
comment_id |
int
|
The |
body_element |
_Element
|
The |
CommentNotFoundError ¶
Bases: DocxPlusError, KeyError
Raised when no <w:comment> with the requested id exists.
Subclasses :class:KeyError so existing except KeyError: clauses
still catch it; also :class:DocxPlusError per SPEC §9.7.
add_comment ¶
add_comment(
target: CommentTarget,
text: str,
*,
author: str = "",
initials: str | None = None,
id_registry: CommentIdRegistry | None = None,
) -> CommentRef
Anchor a comment to a run, paragraph, or run range.
Writes the three body-side OOXML elements python-docx skips
(w:commentRangeStart, w:commentRangeEnd, the
CommentReference marker run) plus the comment body entry in
comments.xml. The comments part is created on first use.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target
|
CommentTarget
|
Where the comment anchors.
|
required |
text
|
str
|
Comment body text. Whitespace is preserved
( |
required |
author
|
str
|
Author shown in the review pane. The empty string is
legal and is what python-docx's own |
''
|
initials
|
str | None
|
Author initials shown alongside the author. |
None
|
id_registry
|
CommentIdRegistry | None
|
Pre-existing registry to share across an editing
session (useful when inserting many comments). A fresh
:class: |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
A |
CommentRef
|
class: |
CommentRef
|
to the comment body element in |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
TypeError
|
If |
Example
from docx import Document from docx_plus.comments import add_comment doc = Document() p = doc.add_paragraph("Hello world") ref = add_comment(p, "Greeting", author="Reviewer")
Source code in docx_plus/comments/anchor.py
edit_comment ¶
Replace the body text of an existing comment in place.
Removes all child block-level content of the matching <w:comment>
element and appends a fresh paragraph with text as its run. The
<w:comment> element's attributes (w:author, w:date,
w:initials) are preserved — only the body content changes. The
body-side range markers and reference run are also untouched, so the
comment stays anchored to the same text range.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
doc
|
Document
|
The python-docx :class: |
required |
comment_id
|
int
|
The |
required |
text
|
str
|
New comment body text. Whitespace is preserved
( |
required |
Raises:
| Type | Description |
|---|---|
CommentNotFoundError
|
If no comment with |
Source code in docx_plus/comments/anchor.py
delete_comment ¶
Remove all traces of a comment from the document.
Removes:
- The
<w:comment>body incomments.xml - Every
<w:commentRangeStart>and<w:commentRangeEnd>marker in the document body - The reference run hosting
<w:commentReference>
Idempotent: deleting a comment id that doesn't exist is a no-op.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
doc
|
Document
|
The python-docx :class: |
required |
comment_id
|
int
|
The |
required |
Source code in docx_plus/comments/anchor.py
clear_all_comments ¶
Remove every comment in the document.
Single-pass: walks the document body once removing every
<w:commentRangeStart>, <w:commentRangeEnd>, and
<w:commentReference> marker regardless of id, then walks
comments.xml once removing every <w:comment> entry.
Idempotent: a document with no comments is a no-op.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
doc
|
Document
|
The python-docx :class: |
required |
remove_part
|
bool
|
When |
False
|