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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# Copyright (c) 2010-2024 openpyxl
 
"""
Generic serialisable classes
"""
from .base import (
    Convertible,
    Bool,
    Descriptor,
    NoneSet,
    MinMax,
    Set,
    Float,
    Integer,
    String,
    )
from openpyxl.compat import safe_string
from openpyxl.xml.functions import Element, localname, whitespace
 
 
class Nested(Descriptor):
 
    nested = True
    attribute = "val"
 
    def __set__(self, instance, value):
        if hasattr(value, "tag"):
            tag = localname(value)
            if tag != self.name:
                raise ValueError("Tag does not match attribute")
 
            value = self.from_tree(value)
        super().__set__(instance, value)
 
 
    def from_tree(self, node):
        return node.get(self.attribute)
 
 
    def to_tree(self, tagname=None, value=None, namespace=None):
        namespace = getattr(self, "namespace", namespace)
        if value is not None:
            if namespace is not None:
                tagname = "{%s}%s" % (namespace, tagname)
            value = safe_string(value)
            return Element(tagname, {self.attribute:value})
 
 
class NestedValue(Nested, Convertible):
    """
    Nested tag storing the value on the 'val' attribute
    """
    pass
 
 
class NestedText(NestedValue):
    """
    Represents any nested tag with the value as the contents of the tag
    """
 
 
    def from_tree(self, node):
        return node.text
 
 
    def to_tree(self, tagname=None, value=None, namespace=None):
        namespace = getattr(self, "namespace", namespace)
        if value is not None:
            if namespace is not None:
                tagname = "{%s}%s" % (namespace, tagname)
            el = Element(tagname)
            el.text = safe_string(value)
            whitespace(el)
            return el
 
 
class NestedFloat(NestedValue, Float):
 
    pass
 
 
class NestedInteger(NestedValue, Integer):
 
    pass
 
 
class NestedString(NestedValue, String):
 
    pass
 
 
class NestedBool(NestedValue, Bool):
 
 
    def from_tree(self, node):
        return node.get("val", True)
 
 
class NestedNoneSet(Nested, NoneSet):
 
    pass
 
 
class NestedSet(Nested, Set):
 
    pass
 
 
class NestedMinMax(Nested, MinMax):
 
    pass
 
 
class EmptyTag(Nested, Bool):
 
    """
    Boolean if a tag exists or not.
    """
 
    def from_tree(self, node):
        return True
 
 
    def to_tree(self, tagname=None, value=None, namespace=None):
        if value:
            namespace = getattr(self, "namespace", namespace)
            if namespace is not None:
                tagname = "{%s}%s" % (namespace, tagname)
            return Element(tagname)