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

1from xml.dom import minidom 

2import copy 

3import enum 

4 

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 

10 

11 

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) 

16 

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() 

23 

24 setattr(obj, self.att_name, value) 

25 

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 

34 

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 

39 

40 def default(self): 

41 return SifValue(copy.deepcopy(self.type.default_value)) 

42 

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 

47 

48 

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 

54 

55 def _def(self): 

56 from ..api import Def 

57 return Def 

58 

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() 

74 

75 setattr(obj, self.att_name, value) 

76 

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 

90 

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 

97 

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)) 

102 

103 

104class XmlDynamicListParam(XmlDescriptor): 

105 _tag = "dynamic_list" 

106 

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 

112 

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)) 

122 

123 def _value_to_dom(self, val, dom: minidom.Document): 

124 return val.to_dom(dom, self.type) 

125 

126 def from_xml(self, obj, parent: minidom.Element, registry: ObjectRegistry): 

127 values = [] 

128 

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 

140 

141 setattr(obj, self.att_name, values) 

142 

143 def _value_from_dom(self, element, registry): 

144 return SifAstNode.from_dom(element, self.type, registry) 

145 

146 def from_python(self, value): 

147 return value 

148 

149 def default(self): 

150 return [] 

151 

152 

153class XmlStaticListParam(XmlDynamicListParam): 

154 _tag = "static_list" 

155 

156 def _value_to_dom(self, val, dom: minidom.Document): 

157 return self.type.value_to_xml_element(val, dom) 

158 

159 def _value_from_dom(self, element: minidom.Element, registry: ObjectRegistry): 

160 return self.type.value_from_xml_element(element, registry)