Skip to content

Reading Font.highlight_color raises ValueError for valid w:highlight w:val="none" #1559

@mithunvoe

Description

@mithunvoe

Summary

Reading Font.highlight_color on a run whose <w:highlight> element has w:val="none" raises:

ValueError: WD_COLOR_INDEX has no XML mapping for 'none'

none is a valid ST_HighlightColor value — Word writes <w:highlight w:val="none"/> when a highlight is explicitly cleared from a run. Because the exception is raised during parsing (any access to font.highlight_color), it aborts processing of the entire document, not just the affected run.

Environment

  • python-docx 1.2.0
  • Python 3.12

Reproduction

from docx import Document
from docx.oxml.ns import qn

doc = Document()
r = doc.add_paragraph().add_run("hi")._r
hl = r.get_or_add_rPr().makeelement(qn("w:highlight"), {qn("w:val"): "none"})
r.get_or_add_rPr().append(hl)

doc.paragraphs[0].runs[0].font.highlight_color
# ValueError: WD_COLOR_INDEX has no XML mapping for 'none'

Traceback bottoms out in BaseXmlEnum.from_xml() (docx/enum/base.py), via CT_Highlight.valhighlight_val.

Root cause

WD_COLOR_INDEX (docx/enum/text.py) maps every ST_HighlightColor value except none. CT_RPr.highlight_val does return highlight.val, and the RequiredAttribute("w:val", WD_COLOR_INDEX) descriptor calls WD_COLOR_INDEX.from_xml("none"), which has no member and raises.

Proposed fix

none semantically means "not highlighted" — exactly what python-docx already represents as None (the value returned when no w:highlight element is present, and the value the highlight_val setter writes by removing the element). So map the explicit none value to None in the getter:

@property
def highlight_val(self) -> WD_COLOR_INDEX | None:
    highlight = self.highlight
    if highlight is None:
        return None
    if highlight.get(qn("w:val")) == "none":
        return None
    return highlight.val

none is the only ST_HighlightColor value absent from WD_COLOR_INDEX, so this closes the gap completely without an enum-value collision (a none enum member would have no distinct MS-API integer — AUTO already occupies 0).

I have a branch with this fix plus a unit test and will open a PR referencing this issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions