Skip to content

Commit edf8f71

Browse files
authored
Merge pull request #31 from hhy827/fix/issue-30-subelement-dispatch
fix(oxml): use _append_child for cell/run text + run-style modifier (closes #30)
2 parents aba3251 + 912ff26 commit edf8f71

2 files changed

Lines changed: 56 additions & 8 deletions

File tree

src/hwpx/oxml/document.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2031,17 +2031,21 @@ def _size_element(self) -> ET.Element:
20312031
def _ensure_text_element(self) -> ET.Element:
20322032
sublist = self.element.find(f"{_HP}subList")
20332033
if sublist is None:
2034-
sublist = ET.SubElement(self.element, f"{_HP}subList", _default_sublist_attributes())
2034+
sublist = _append_child(
2035+
self.element, f"{_HP}subList", _default_sublist_attributes()
2036+
)
20352037
paragraph = sublist.find(f"{_HP}p")
20362038
if paragraph is None:
2037-
paragraph = ET.SubElement(sublist, f"{_HP}p", _default_cell_paragraph_attributes())
2039+
paragraph = _append_child(
2040+
sublist, f"{_HP}p", _default_cell_paragraph_attributes()
2041+
)
20382042
_clear_paragraph_layout_cache(paragraph)
20392043
run = paragraph.find(f"{_HP}run")
20402044
if run is None:
2041-
run = ET.SubElement(paragraph, f"{_HP}run", {"charPrIDRef": "0"})
2045+
run = _append_child(paragraph, f"{_HP}run", {"charPrIDRef": "0"})
20422046
text = run.find(f"{_HP}t")
20432047
if text is None:
2044-
text = ET.SubElement(run, f"{_HP}t")
2048+
text = _append_child(run, f"{_HP}t")
20452049
return text
20462050

20472051
@property
@@ -4536,9 +4540,9 @@ def modifier(element: ET.Element) -> None:
45364540
element.remove(child)
45374541

45384542
if target[0]:
4539-
ET.SubElement(element, f"{_HH}bold")
4543+
_append_child(element, f"{_HH}bold")
45404544
if target[1]:
4541-
ET.SubElement(element, f"{_HH}italic")
4545+
_append_child(element, f"{_HH}italic")
45424546

45434547
underline_attrs = dict(base_underline_attrs)
45444548
if target[2]:
@@ -4550,14 +4554,14 @@ def modifier(element: ET.Element) -> None:
45504554
underline_attrs["color"] = base_underline_attrs["color"]
45514555
if "color" not in underline_attrs:
45524556
underline_attrs["color"] = "#000000"
4553-
ET.SubElement(element, f"{_HH}underline", underline_attrs)
4557+
_append_child(element, f"{_HH}underline", underline_attrs)
45544558
else:
45554559
attrs = dict(base_underline_attrs)
45564560
attrs["type"] = "NONE"
45574561
attrs.setdefault("shape", base_underline_attrs.get("shape", "SOLID"))
45584562
if "color" in base_underline_attrs:
45594563
attrs["color"] = base_underline_attrs["color"]
4560-
ET.SubElement(element, f"{_HH}underline", attrs)
4564+
_append_child(element, f"{_HH}underline", attrs)
45614565

45624566
element = header.ensure_char_property(
45634567
predicate=predicate,

tests/test_document_formatting.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -750,3 +750,47 @@ def test_paragraph_add_shape_and_control_updates_attributes() -> None:
750750
control.set_attribute("id", None)
751751
assert control.get_attribute("id") is None
752752
assert section.dirty is True
753+
754+
755+
# ---------------------------------------------------------------------------
756+
# Regression: issue #30 — stdlib ET.SubElement called on lxml _Element
757+
# https://github.com/airmang/python-hwpx/issues/30
758+
# ---------------------------------------------------------------------------
759+
760+
761+
def test_issue_30_set_cell_text_on_blank_cell() -> None:
762+
"""Setting ``cell.text`` on a cell that lacks ``<hp:subList>/<hp:p>/<hp:run>``
763+
must not raise ``TypeError``.
764+
765+
Before the fix, ``HwpxOxmlTableCell._ensure_text_element`` used
766+
``ET.SubElement`` (stdlib) on ``self.element`` which is an
767+
``lxml.etree._Element``. This reproduces the call path reported by
768+
``@devnoff`` in issue #30 and by downstream consumers running
769+
``table.set_cell_text(...)`` on freshly created tables.
770+
"""
771+
772+
document = HwpxDocument.new()
773+
table = document.add_table(rows=2, cols=2)
774+
775+
# Both the explicit API and the property setter must succeed.
776+
table.set_cell_text(0, 0, "hello")
777+
cells = list(table.rows[1].cells)
778+
cells[1].text = "world"
779+
780+
assert table.rows[0].cells[0].text == "hello"
781+
assert table.rows[1].cells[1].text == "world"
782+
783+
784+
def test_issue_30_add_run_bold() -> None:
785+
"""``paragraph.add_run(text, bold=True)`` must not raise ``TypeError``.
786+
787+
Before the fix, ``ensure_run_style``'s ``modifier`` closure called
788+
``ET.SubElement(element, ...)`` where ``element`` is an lxml element.
789+
This is the original reproduction from the body of issue #30.
790+
"""
791+
792+
document = HwpxDocument.new()
793+
paragraph = document.add_paragraph("")
794+
run = paragraph.add_run("hello", bold=True)
795+
796+
assert run.text == "hello"

0 commit comments

Comments
 (0)