File: builder.py

package info (click to toggle)
python-a38 0.1.8-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 440 kB
  • sloc: python: 4,065; xml: 174; makefile: 80; sh: 14
file content (85 lines) | stat: -rw-r--r-- 2,657 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# This module builds XML trees but does not parse them, so it does not need
# defusedxml
import xml.etree.ElementTree as ET
from contextlib import contextmanager

try:
    import lxml.etree
    HAVE_LXML = True
except ModuleNotFoundError:
    HAVE_LXML = False


class Builder:
    def __init__(self, etreebuilder=None):
        if etreebuilder is None:
            etreebuilder = ET.TreeBuilder()
        self.etreebuilder = etreebuilder
        self.default_namespace = None

    def _decorate_tag_name(self, tag: str):
        if self.default_namespace is not None and not tag.startswith("{"):
            return "{" + self.default_namespace + "}" + tag
        return tag

    def add(self, tag: str, value: str, **attrs):
        tag = self._decorate_tag_name(tag)
        self.etreebuilder.start(tag, attrs)
        if value is not None:
            self.etreebuilder.data(value)
        self.etreebuilder.end(tag)

    @contextmanager
    def element(self, tag: str, **attrs):
        tag = self._decorate_tag_name(tag)
        self.etreebuilder.start(tag, attrs)
        yield self
        self.etreebuilder.end(tag)

    @contextmanager
    def override_default_namespace(self, ns):
        b = Builder(self.etreebuilder)
        b.default_namespace = ns
        yield b

    def get_tree(self):
        root = self.etreebuilder.close()
        return ET.ElementTree(root)


if HAVE_LXML:
    class LXMLBuilder:
        def __init__(self, etreebuilder=None):
            if etreebuilder is None:
                etreebuilder = lxml.etree.TreeBuilder()
            self.etreebuilder = etreebuilder
            self.default_namespace = None

        def _decorate_tag_name(self, tag: str):
            if self.default_namespace is not None and not tag.startswith("{"):
                return "{" + self.default_namespace + "}" + tag
            return tag

        def add(self, tag: str, value: str, **attrs):
            tag = self._decorate_tag_name(tag)
            self.etreebuilder.start(tag, attrs)
            if value is not None:
                self.etreebuilder.data(value)
            self.etreebuilder.end(tag)

        @contextmanager
        def element(self, tag: str, **attrs):
            tag = self._decorate_tag_name(tag)
            self.etreebuilder.start(tag, attrs)
            yield self
            self.etreebuilder.end(tag)

        @contextmanager
        def override_default_namespace(self, ns):
            b = Builder(self.etreebuilder)
            b.default_namespace = ns
            yield b

        def get_tree(self):
            root = self.etreebuilder.close()
            return lxml.etree.ElementTree(root)