Coverage for /home/runner/work/viur-core/viur-core/viur/src/viur/core/render/xml/default.py: 0%

127 statements  

« prev     ^ index     » next       coverage.py v7.6.1, created at 2024-09-03 13:41 +0000

1import typing as t 

2 

3from viur.core.bones import * 

4from viur.core import db 

5from xml.dom import minidom 

6from datetime import datetime, date, time 

7 

8from viur.core.skeleton import SkeletonInstance 

9 

10 

11def serializeXML(data): 

12 def recursiveSerializer(data, element): 

13 if isinstance(data, dict): 

14 element.setAttribute('ViurDataType', 'dict') 

15 for key in data.keys(): 

16 docElem = doc.createElement("entry") 

17 docElem.setAttribute('KeyName', str(key)) 

18 childElement = recursiveSerializer(data[key], docElem) 

19 element.appendChild(childElement) 

20 elif isinstance(data, (tuple, list)): 

21 element.setAttribute('ViurDataType', 'list') 

22 for value in data: 

23 childElement = recursiveSerializer(value, doc.createElement('entry')) 

24 element.appendChild(childElement) 

25 else: 

26 if isinstance(data, bool): 

27 element.setAttribute('ViurDataType', 'boolean') 

28 elif isinstance(data, float) or isinstance(data, int): 

29 element.setAttribute('ViurDataType', 'numeric') 

30 elif isinstance(data, str): 

31 element.setAttribute('ViurDataType', 'string') 

32 elif isinstance(data, datetime) or isinstance(data, date) or isinstance(data, time): 

33 if isinstance(data, datetime): 

34 element.setAttribute('ViurDataType', 'datetime') 

35 elif isinstance(data, date): 

36 element.setAttribute('ViurDataType', 'date') 

37 else: 

38 element.setAttribute('ViurDataType', 'time') 

39 data = data.isoformat() 

40 elif isinstance(data, db.KeyClass): 

41 element.setAttribute('ViurDataType', 'dbkey') 

42 data = data.to_legacy_urlsafe().decode("ASCII") 

43 elif data is None: 

44 element.setAttribute('ViurDataType', 'none') 

45 data = "" 

46 else: 

47 raise NotImplementedError(f"Type {type(data)} is not supported!") 

48 element.appendChild(doc.createTextNode(str(data))) 

49 return element 

50 

51 dom = minidom.getDOMImplementation() 

52 doc = dom.createDocument(None, u"ViurResult", None) 

53 elem = doc.childNodes[0] 

54 return recursiveSerializer(data, elem).toprettyxml(encoding="UTF-8") 

55 

56 

57class DefaultRender(object): 

58 kind = "xml" 

59 

60 def __init__(self, parent=None, *args, **kwargs): 

61 super(DefaultRender, self).__init__(*args, **kwargs) 

62 

63 

64 def renderTextExtension(self, ext): 

65 e = ext() 

66 return ({"name": e.name, 

67 "descr": str(e.descr), 

68 "skel": e.dataSkel().structure()}) 

69 

70 def renderBoneValue(self, bone, skel, key): 

71 boneVal = skel[key] 

72 if bone.languages and bone.multiple: 

73 res = {} 

74 for language in bone.languages: 

75 if boneVal and language in boneVal and boneVal[language]: 

76 res[language] = [self.renderSingleBoneValue(v, bone, skel, key) for v in boneVal[language]] 

77 else: 

78 res[language] = [] 

79 elif bone.languages: 

80 res = {} 

81 for language in bone.languages: 

82 if boneVal and language in boneVal and boneVal[language] is not None: 

83 res[language] = self.renderSingleBoneValue(boneVal[language], bone, skel, key) 

84 else: 

85 res[language] = None 

86 elif bone.multiple: 

87 res = [self.renderSingleBoneValue(v, bone, skel, key) for v in boneVal] if boneVal else None 

88 else: 

89 res = self.renderSingleBoneValue(boneVal, bone, skel, key) 

90 return res 

91 

92 def renderSingleBoneValue(self, value: t.Any, bone: baseBone, skel: SkeletonInstance, key: str) -> dict: 

93 """ 

94 Renders the value of a bone. 

95 

96 It can be overridden and super-called from a custom renderer. 

97 

98 :param bone: The bone which value should be rendered. 

99 

100 :return: A dict containing the rendered attributes. 

101 """ 

102 if isinstance(bone, DateBone): 

103 if value: 

104 if bone.date and bone.time: 

105 return value.strftime("%d.%m.%Y %H:%M:%S") 

106 elif bone.date: 

107 return value.strftime("%d.%m.%Y") 

108 return value.strftime("%H:%M:%S") 

109 elif isinstance(bone, RelationalBone): 

110 if isinstance(value, list): 

111 tmpList = [] 

112 for k in value: 

113 tmpList.append({ 

114 "dest": self.renderSkelValues(k["dest"]), 

115 "rel": self.renderSkelValues(k.get("rel")) 

116 }) 

117 return tmpList 

118 elif isinstance(value, dict): 

119 return { 

120 "dest": self.renderSkelValues(value["dest"]), 

121 "rel": self.renderSkelValues(value.get("rel")) 

122 } 

123 elif isinstance(bone, PasswordBone): 

124 return "" 

125 else: 

126 return value 

127 

128 def renderSkelValues(self, skel: SkeletonInstance): 

129 """ 

130 Prepares values of one :class:`viur.core.skeleton.Skeleton` or a list of skeletons for output. 

131 

132 :param skel: Skeleton which contents will be processed. 

133 

134 :returns: A dictionary or list of dictionaries. 

135 :rtype: dict 

136 """ 

137 if skel is None: 

138 return None 

139 elif isinstance(skel, dict): 

140 return skel 

141 

142 res = {} 

143 for key, bone in skel.items(): 

144 res[key] = self.renderBoneValue(bone, skel, key) 

145 

146 return res 

147 

148 def renderEntry(self, skel, action, params=None): 

149 res = { 

150 "action": action, 

151 "params": params, 

152 "values": self.renderSkelValues(skel), 

153 "structure": skel.structure(), 

154 "errors": [{"severity": x.severity.value, "fieldPath": x.fieldPath, "errorMessage": x.errorMessage, 

155 "invalidatedFields": x.invalidatedFields} for x in skel.errors] 

156 } 

157 

158 return serializeXML(res) 

159 

160 def view(self, skel, action="view", params=None, *args, **kwargs): 

161 return self.renderEntry(skel, action, params) 

162 

163 def add(self, skel, action="add", params=None, *args, **kwargs): 

164 return self.renderEntry(skel, action, params) 

165 

166 def edit(self, skel, action="edit", params=None, *args, **kwargs): 

167 return self.renderEntry(skel, action, params) 

168 

169 def list(self, skellist, action="list", tpl=None, params=None, **kwargs): 

170 res = {} 

171 skels = [] 

172 

173 for skel in skellist: 

174 skels.append(self.renderSkelValues(skel)) 

175 

176 res["skellist"] = skels 

177 

178 if (len(skellist) > 0): 

179 res["structure"] = skellist[0].structure() 

180 else: 

181 res["structure"] = None 

182 

183 res["action"] = action 

184 res["params"] = params 

185 res["cursor"] = skellist.getCursor() 

186 

187 return serializeXML(res) 

188 

189 def editSuccess(self, skel, params=None, **kwargs): 

190 return serializeXML("OKAY") 

191 

192 def addSuccess(self, skel, params=None, **kwargs): 

193 return serializeXML("OKAY") 

194 

195 def deleteSuccess(self, skel, params=None, *args, **kwargs): 

196 return serializeXML("OKAY")