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.3, created at 2024-10-16 22:16 +0000
« prev ^ index » next coverage.py v7.6.3, created at 2024-10-16 22:16 +0000
1import typing as t
3from viur.core.bones import *
4from viur.core import db
5from xml.dom import minidom
6from datetime import datetime, date, time
8from viur.core.skeleton import SkeletonInstance
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
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")
57class DefaultRender(object):
58 kind = "xml"
60 def __init__(self, parent=None, *args, **kwargs):
61 super(DefaultRender, self).__init__(*args, **kwargs)
64 def renderTextExtension(self, ext):
65 e = ext()
66 return ({"name": e.name,
67 "descr": str(e.descr),
68 "skel": e.dataSkel().structure()})
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
92 def renderSingleBoneValue(self, value: t.Any, bone: baseBone, skel: SkeletonInstance, key: str) -> dict:
93 """
94 Renders the value of a bone.
96 It can be overridden and super-called from a custom renderer.
98 :param bone: The bone which value should be rendered.
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
128 def renderSkelValues(self, skel: SkeletonInstance):
129 """
130 Prepares values of one :class:`viur.core.skeleton.Skeleton` or a list of skeletons for output.
132 :param skel: Skeleton which contents will be processed.
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
142 res = {}
143 for key, bone in skel.items():
144 res[key] = self.renderBoneValue(bone, skel, key)
146 return res
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 }
158 return serializeXML(res)
160 def view(self, skel, action="view", params=None, *args, **kwargs):
161 return self.renderEntry(skel, action, params)
163 def add(self, skel, action="add", params=None, *args, **kwargs):
164 return self.renderEntry(skel, action, params)
166 def edit(self, skel, action="edit", params=None, *args, **kwargs):
167 return self.renderEntry(skel, action, params)
169 def list(self, skellist, action="list", tpl=None, params=None, **kwargs):
170 res = {}
171 skels = []
173 for skel in skellist:
174 skels.append(self.renderSkelValues(skel))
176 res["skellist"] = skels
178 if (len(skellist) > 0):
179 res["structure"] = skellist[0].structure()
180 else:
181 res["structure"] = None
183 res["action"] = action
184 res["params"] = params
185 res["cursor"] = skellist.getCursor()
187 return serializeXML(res)
189 def editSuccess(self, skel, params=None, **kwargs):
190 return serializeXML("OKAY")
192 def addSuccess(self, skel, params=None, **kwargs):
193 return serializeXML("OKAY")
195 def deleteSuccess(self, skel, params=None, *args, **kwargs):
196 return serializeXML("OKAY")