Coverage for lib/lottie/parsers/sif/xml/animatable.py: 86%
119 statements
« prev ^ index » next coverage.py v7.2.2, created at 2023-03-20 16:17 +0100
« prev ^ index » next coverage.py v7.2.2, created at 2023-03-20 16:17 +0100
1from xml.dom import minidom
2import copy
3import enum
5from .core_nodes import XmlDescriptor, XmlSimpleElement, ValueReference
6from .utils import *
7from lottie.nvector import NVector
8from lottie.parsers.sif.ast_impl.base import SifAstNode, SifValue
9from lottie.parsers.sif.sif.core import ObjectRegistry, TypeDescriptor, noop
12class XmlAnimatable(XmlDescriptor):
13 def __init__(self, name, typename, default=None, type_wrapper=noop):
14 super().__init__(name)
15 self.type = TypeDescriptor(typename, default, type_wrapper)
17 def from_xml(self, obj, parent: minidom.Element, registry: ObjectRegistry, param: TypeDescriptor = None):
18 cn = xml_first_element_child(parent, self.name)
19 if cn: 19 ↛ 22line 19 didn't jump to line 22, because the condition on line 19 was never false
20 value = SifAstNode.from_dom(xml_first_element_child(cn), self.type_for(param), registry)
21 else:
22 value = self.default()
24 setattr(obj, self.att_name, value)
26 def to_xml(self, obj, parent: minidom.Element, dom: minidom.Document, type: TypeDescriptor = None):
27 value = getattr(obj, self.att_name)
28 if isinstance(value, SifValue) and isinstance(value.value, ValueReference): 28 ↛ 29line 28 didn't jump to line 29, because the condition on line 28 was never true
29 parent.setAttribute(self.name, ":" + value.value.id)
30 return
31 param = parent.appendChild(dom.createElement(self.name))
32 param.appendChild(value.to_dom(dom, self.type_for(type)))
33 return param
35 def from_python(self, value):
36 if not isinstance(value, SifAstNode): 36 ↛ 37line 36 didn't jump to line 37, because the condition on line 36 was never true
37 raise ValueError("%s isn't a valid value for %s" % (value, self.name))
38 return value
40 def default(self):
41 return SifValue(copy.deepcopy(self.type.default_value))
43 def type_for(self, param: TypeDescriptor):
44 if param is not None and self.type.typename == "_recurse": 44 ↛ 45line 44 didn't jump to line 45, because the condition on line 44 was never true
45 return param
46 return self.type
49class XmlParam(XmlDescriptor):
50 def __init__(self, name, typename, default=None, type_wrapper=noop, static=False):
51 super().__init__(name)
52 self.type = TypeDescriptor(typename, default, type_wrapper)
53 self.static = static
55 def _def(self):
56 from ..api import Def
57 return Def
59 def from_xml(self, obj, parent: minidom.Element, registry: ObjectRegistry):
60 for cn in xml_child_elements(parent, "param"): 60 ↛ 73line 60 didn't jump to line 73, because the loop on line 60 didn't complete
61 if cn.getAttribute("name") == self.name:
62 use = cn.getAttribute("use")
63 if use: 63 ↛ 64line 63 didn't jump to line 64, because the condition on line 63 was never true
64 value = registry.get_object(use)
65 else:
66 value_node = xml_first_element_child(cn)
67 if self.static:
68 value = self.type.value_from_xml_element(value_node, registry)
69 else:
70 value = SifAstNode.from_dom(value_node, self.type, registry)
71 break
72 else:
73 value = self.default()
75 setattr(obj, self.att_name, value)
77 def to_xml(self, obj, parent: minidom.Element, dom: minidom.Document):
78 param = parent.appendChild(dom.createElement("param"))
79 param.setAttribute("name", self.name)
80 value = getattr(obj, self.att_name)
81 if isinstance(value, self._def()): 81 ↛ 82line 81 didn't jump to line 82, because the condition on line 81 was never true
82 param.setAttribute("use", ":" + value.id)
83 else:
84 if self.static:
85 elem = self.type.value_to_xml_element(value, dom)
86 else:
87 elem = value.to_dom(dom, self.type)
88 param.appendChild(elem)
89 return param
91 def from_python(self, value):
92 if self.static:
93 return self.type.type_wrapper(value)
94 if not isinstance(value, (SifAstNode, self._def())): 94 ↛ 95line 94 didn't jump to line 95, because the condition on line 94 was never true
95 raise ValueError("%s isn't a valid value for %s" % (value, self.name))
96 return value
98 def default(self):
99 if self.static:
100 return copy.deepcopy(self.type.default_value)
101 return SifValue(copy.deepcopy(self.type.default_value))
104class XmlDynamicListParam(XmlDescriptor):
105 _tag = "dynamic_list"
107 def __init__(self, name, typename, att_name=None):
108 super().__init__(name)
109 self.type = TypeDescriptor(typename)
110 if att_name is not None:
111 self.att_name = att_name
113 def to_xml(self, obj, parent: minidom.Element, dom: minidom.Document):
114 param = parent.appendChild(dom.createElement("param"))
115 param.setAttribute("name", self.name)
116 dyl = param.appendChild(dom.createElement(self._tag))
117 dyl.setAttribute("type", self.type.typename)
118 values = getattr(obj, self.att_name)
119 for val in values:
120 entry = dyl.appendChild(dom.createElement("entry"))
121 entry.appendChild(self._value_to_dom(val, dom))
123 def _value_to_dom(self, val, dom: minidom.Document):
124 return val.to_dom(dom, self.type)
126 def from_xml(self, obj, parent: minidom.Element, registry: ObjectRegistry):
127 values = []
129 for cn in xml_child_elements(parent, "param"): 129 ↛ 141line 129 didn't jump to line 141, because the loop on line 129 didn't complete
130 if cn.getAttribute("name") == self.name:
131 list = xml_first_element_child(cn)
132 if list.getAttribute("type") != self.type.typename: 132 ↛ 133line 132 didn't jump to line 133, because the condition on line 132 was never true
133 raise ValueError(
134 "Wrong type for %s: got %s instead of %s" %
135 (self.name, self.type.typename, list.getAttribute("type"))
136 )
137 for entry in xml_child_elements(list, "entry"):
138 values.append(self._value_from_dom(xml_first_element_child(entry), registry))
139 break
141 setattr(obj, self.att_name, values)
143 def _value_from_dom(self, element, registry):
144 return SifAstNode.from_dom(element, self.type, registry)
146 def from_python(self, value):
147 return value
149 def default(self):
150 return []
153class XmlStaticListParam(XmlDynamicListParam):
154 _tag = "static_list"
156 def _value_to_dom(self, val, dom: minidom.Document):
157 return self.type.value_to_xml_element(val, dom)
159 def _value_from_dom(self, element: minidom.Element, registry: ObjectRegistry):
160 return self.type.value_from_xml_element(element, registry)