Skip to content

Commit 20ff08c

Browse files
authored
Merge pull request #29 from BlackBoiler/DEV-4746-pickle-serialize
v1.2.0: Support Serialization of python-docx/ lxml.Etree elements
2 parents 0fa0747 + 94ba476 commit 20ff08c

File tree

4 files changed

+27
-1
lines changed

4 files changed

+27
-1
lines changed

HISTORY.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@
33
Release History
44
---------------
55

6+
1.2.0 (2025-05-22)
7+
++++++++++++++++++
8+
- DEV-4746: Support Serialization of python-docx/ lxml.Etree elements
9+
10+
611
1.1.0 (2025-03-25)
712
++++++++++++++++++
813
- DEV-4646: add new color_val property to ``CT_RPr``

src/docx/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
if TYPE_CHECKING:
1414
from docx.opc.part import Part
1515

16-
__version__ = "1.1.0"
16+
__version__ = "1.2.0"
1717

1818

1919
__all__ = ["Document"]

src/docx/oxml/parser.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from __future__ import annotations
66

77
from typing import TYPE_CHECKING, Dict, Type, cast
8+
import copyreg
89

910
from lxml import etree
1011

@@ -19,6 +20,21 @@
1920
oxml_parser = etree.XMLParser(remove_blank_text=True, resolve_entities=False)
2021
oxml_parser.set_element_class_lookup(element_class_lookup)
2122

23+
# -- serialization support --
24+
def _pickle_element(elem):
25+
"""Function for pickling lxml.etree._Element objects."""
26+
xml_str = etree.tostring(elem)
27+
return _deserialize_oxml_element, (xml_str,)
28+
29+
30+
def _deserialize_oxml_element(xml_str):
31+
"""Deserialize bytes back into an object using parse_xml."""
32+
return parse_xml(xml_str)
33+
34+
35+
copyreg.pickle(etree._Element, _pickle_element)
36+
# --
37+
2238

2339
def parse_xml(xml: str | bytes) -> "BaseOxmlElement":
2440
"""Root lxml element obtained by parsing XML character string `xml`.
@@ -39,6 +55,7 @@ def register_element_cls(tag: str, cls: Type["BaseOxmlElement"]):
3955
nspfx, tagroot = tag.split(":")
4056
namespace = element_class_lookup.get_namespace(nsmap[nspfx])
4157
namespace[tagroot] = cls
58+
copyreg.pickle(cls, _pickle_element)
4259

4360

4461
def OxmlElement(

src/docx/shared.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,10 @@ def __str__(self):
142142
"""Return a hex string rgb value, like '3C2F80'."""
143143
return "%02X%02X%02X" % self
144144

145+
def __reduce__(self):
146+
# Return a tuple of (callable, args) that will recreate this object
147+
return RGBColor, (self[0], self[1], self[2])
148+
145149
@classmethod
146150
def from_string(cls, rgb_hex_str: str) -> RGBColor:
147151
"""Return a new instance from an RGB color hex string like ``'3C2F80'``."""

0 commit comments

Comments
 (0)