|
3 | 3 | from __future__ import annotations
|
4 | 4 |
|
5 | 5 | import re
|
6 |
| -from typing import Any, Callable, List |
| 6 | +from typing import Any, Callable, Dict, List, Tuple |
7 | 7 |
|
8 | 8 | from lxml import etree
|
9 | 9 | from lxml.etree import ElementBase
|
10 | 10 |
|
11 | 11 | from docx.oxml.exceptions import InvalidXmlError
|
12 | 12 | from docx.oxml.ns import NamespacePrefixedTag, nsmap, qn
|
13 |
| -from docx.oxml.parser import OxmlElement |
14 | 13 | from docx.shared import lazyproperty
|
15 | 14 |
|
16 | 15 |
|
@@ -84,7 +83,11 @@ def _parse_line(cls, line):
|
84 | 83 | class MetaOxmlElement(type):
|
85 | 84 | """Metaclass for BaseOxmlElement."""
|
86 | 85 |
|
87 |
| - def __init__(cls, clsname, bases, clsdict): |
| 86 | + def __new__(cls, clsname: str, bases: Tuple[type, ...], clsdict: Dict[str, Any]): |
| 87 | + bases = (*bases, etree.ElementBase) |
| 88 | + return super().__new__(cls, clsname, bases, clsdict) |
| 89 | + |
| 90 | + def __init__(cls, clsname: str, bases: Tuple[type, ...], clsdict: Dict[str, Any]): |
88 | 91 | dispatchable = (
|
89 | 92 | OneAndOnlyOne,
|
90 | 93 | OneOrMore,
|
@@ -326,8 +329,8 @@ def _add_to_class(self, name, method):
|
326 | 329 |
|
327 | 330 | @property
|
328 | 331 | def _creator(self):
|
329 |
| - """Return a function object that creates a new, empty element of the right type, |
330 |
| - having no attributes.""" |
| 332 | + """Callable that creates an empty element of the right type, with no attrs.""" |
| 333 | + from docx.oxml.parser import OxmlElement |
331 | 334 |
|
332 | 335 | def new_child_element(obj):
|
333 | 336 | return OxmlElement(self._nsptagname)
|
@@ -609,21 +612,20 @@ def _remove_choice_group_method_name(self):
|
609 | 612 | return "_remove_%s" % self._prop_name
|
610 | 613 |
|
611 | 614 |
|
612 |
| -class _OxmlElementBase(etree.ElementBase): |
| 615 | +class BaseOxmlElement(metaclass=MetaOxmlElement): |
613 | 616 | """Effective base class for all custom element classes.
|
614 | 617 |
|
615 |
| - Adds standardized behavior to all classes in one place. Actual inheritance is from |
616 |
| - BaseOxmlElement below, needed to manage Python 2-3 metaclass declaration |
617 |
| - compatibility. |
| 618 | + Adds standardized behavior to all classes in one place. |
618 | 619 | """
|
619 | 620 |
|
620 |
| - __metaclass__ = MetaOxmlElement |
621 |
| - |
622 | 621 | append: Callable[[ElementBase], None]
|
623 | 622 | find: Callable[[str], ElementBase | None]
|
624 | 623 | findall: Callable[[str], List[ElementBase]]
|
625 |
| - remove: Callable[[ElementBase], None] |
| 624 | + getparent: Callable[[], BaseOxmlElement] |
| 625 | + insert: Callable[[int, BaseOxmlElement], None] |
| 626 | + remove: Callable[[BaseOxmlElement], None] |
626 | 627 | tag: str
|
| 628 | + text: str | None |
627 | 629 |
|
628 | 630 | def __repr__(self):
|
629 | 631 | return "<%s '<%s>' at 0x%0x>" % (
|
@@ -670,13 +672,8 @@ def xpath( # pyright: ignore[reportIncompatibleMethodOverride]
|
670 | 672 |
|
671 | 673 | Provides standard Open XML namespace mapping (`nsmap`) in centralized location.
|
672 | 674 | """
|
673 |
| - return super(BaseOxmlElement, self).xpath(xpath_str, namespaces=nsmap) |
| 675 | + return super().xpath(xpath_str, namespaces=nsmap) |
674 | 676 |
|
675 | 677 | @property
|
676 | 678 | def _nsptag(self) -> str:
|
677 | 679 | return NamespacePrefixedTag.from_clark_name(self.tag)
|
678 |
| - |
679 |
| - |
680 |
| -BaseOxmlElement = MetaOxmlElement( |
681 |
| - "BaseOxmlElement", (etree.ElementBase,), dict(_OxmlElementBase.__dict__) |
682 |
| -) |
0 commit comments