eric7/EricXML/XMLStreamReaderBase.py

branch
eric7
changeset 8351
7d13e08ddb3f
parent 8327
666c2b81cbb7
child 8356
68ec9c3d4de5
equal deleted inserted replaced
8350:74a3b2a6a944 8351:7d13e08ddb3f
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2010 - 2021 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a base class for all of eric7s XML stream writers.
8 """
9
10 import pickle # secok
11 import base64
12
13 from PyQt6.QtCore import QXmlStreamReader, QCoreApplication
14
15 from E5Gui import E5MessageBox
16
17
18 class XMLStreamReaderBase(QXmlStreamReader):
19 """
20 Class implementing a base class for all of eric7s XML stream readers.
21 """
22 def __init__(self, device):
23 """
24 Constructor
25
26 @param device reference to the I/O device to read from (QIODevice)
27 """
28 super().__init__(device)
29
30 def toBool(self, value):
31 """
32 Public method to convert the given value to bool.
33
34 @param value value to be converted ("True", "False", "1", "0")
35 @return converted value (boolean) or None in case of an error
36 """
37 if value.lower() in ["true", "false"]:
38 return value.lower() == "true"
39
40 if value in ["1", "0"]:
41 return bool(int(value))
42
43 self.raiseBadValue(value)
44 return None
45
46 def showErrorMessage(self):
47 """
48 Public method to show an error message.
49 """
50 if self.hasError():
51 if self.device() is not None:
52 msg = QCoreApplication.translate(
53 "XMLStreamReaderBase",
54 "<p>XML parse error in file <b>{0}</b>, line {1},"
55 " column {2}</p><p>Error: {3}</p>").format(
56 self.device().fileName(),
57 self.lineNumber(), self.columnNumber(),
58 self.errorString())
59 else:
60 msg = QCoreApplication.translate(
61 "XMLStreamReaderBase",
62 "<p>XML parse error (line {0},"
63 " column {1})</p><p>Error: {2}</p>").format(
64 self.lineNumber(), self.columnNumber(),
65 self.errorString())
66 E5MessageBox.warning(
67 None,
68 QCoreApplication.translate(
69 "XMLStreamReaderBase", "XML parse error"),
70 msg)
71
72 def raiseUnexpectedStartTag(self, tag):
73 """
74 Public method to raise an error for an unexpected start tag.
75
76 @param tag name of the unexpected tag (string)
77 """
78 self.raiseError(QCoreApplication.translate(
79 "XMLStreamReaderBase", "Unexpected start tag '{0}'.".format(tag)))
80
81 def raiseUnsupportedFormatVersion(self, version):
82 """
83 Public method to raise an error for an unsupported file format version.
84
85 @param version unsupported version (string)
86 """
87 self.raiseError(QCoreApplication.translate(
88 "XMLStreamReaderBase",
89 "File format version '{0}' is not supported.").format(version))
90
91 def raiseBadValue(self, value):
92 """
93 Public method to raise an error for a bad value.
94
95 @param value bad value (string)
96 """
97 self.raiseError(QCoreApplication.translate(
98 "XMLStreamReaderBase", "Bad value: {0}").format(value))
99
100 def readXML(self):
101 """
102 Public method to read and parse the XML document.
103 """
104 pass
105
106 def attribute(self, name, default=""):
107 """
108 Public method to read the given attribute of the current tag.
109
110 @param name name of the attribute (string)
111 @param default default value (string)
112 @return value of the requested tag attribute (string)
113 """
114 try:
115 att = self.attributes().value(name)
116 if att == "":
117 att = default
118 return att
119 except AttributeError:
120 # Work around for PyQt6 < 6.1.1
121 attributes = self.attributes()
122 for attribute in attributes:
123 if attribute.name() == name:
124 value = attribute.value()
125 if not value:
126 value = default
127 break
128 else:
129 value = default
130 return value
131
132 def _skipUnknownElement(self):
133 """
134 Protected method to skip over all unknown elements.
135 """
136 if not self.isStartElement():
137 return
138
139 while not self.atEnd():
140 self.readNext()
141 if self.isEndElement():
142 break
143
144 if self.isStartElement():
145 self._skipUnknownElement()
146
147 def _readBasics(self):
148 """
149 Protected method to read an object of a basic Python type.
150
151 @return Python object read
152 """
153 while not self.atEnd():
154 self.readNext()
155 if self.isStartElement():
156 try:
157 if self.name() == "none":
158 val = None
159 elif self.name() in ("int", "long"):
160 val = int(self.readElementText())
161 elif self.name() == "bool":
162 b = self.readElementText()
163 if b == "True":
164 val = True
165 else:
166 val = False
167 elif self.name() == "float":
168 val = float(self.readElementText())
169 elif self.name() == "complex":
170 real, imag = self.readElementText().split()
171 val = float(real) + float(imag) * 1j
172 elif self.name() == "string":
173 val = self.readElementText()
174 elif self.name() == "bytes":
175 by = bytes([int(b) for b in
176 self.readElementText().split(",")])
177 val = by
178 elif self.name() == "bytearray":
179 by = bytearray([int(b) for b in
180 self.readElementText().split(",")])
181 val = by
182 elif self.name() == "tuple":
183 val = self.__readTuple()
184 return val
185 elif self.name() == "list":
186 val = self.__readList()
187 return val
188 elif self.name() == "dict":
189 val = self.__readDict()
190 return val
191 elif self.name() == "set":
192 val = self.__readSet()
193 return val
194 elif self.name() == "frozenset":
195 val = self.__readFrozenset()
196 return val
197 elif self.name() == "pickle":
198 encoding = self.attribute("encoding")
199 if encoding != "base64":
200 self.raiseError(QCoreApplication.translate(
201 "XMLStreamReaderBase",
202 "Pickle data encoding '{0}' is not"
203 " supported.").format(encoding))
204 continue
205 b64 = self.readElementText()
206 pic = base64.b64decode(b64.encode("ASCII"))
207 val = pickle.loads(pic) # secok
208 else:
209 self._skipUnknownElement()
210 except ValueError as err:
211 self.raiseError(str(err))
212 continue
213
214 if self.isEndElement():
215 if self.name() in [
216 "tuple", "list", "dict", "set", "frozenset"]:
217 return None
218 else:
219 return val
220
221 def __readTuple(self):
222 """
223 Private method to read a Python tuple.
224
225 @return Python tuple
226 """
227 li = []
228 while not self.atEnd():
229 val = self._readBasics()
230 if self.isEndElement() and self.name() == "tuple" and val is None:
231 return tuple(li)
232 else:
233 li.append(val)
234
235 def __readList(self):
236 """
237 Private method to read a Python list.
238
239 @return Python list
240 """
241 li = []
242 while not self.atEnd():
243 val = self._readBasics()
244 if self.isEndElement() and self.name() == "list" and val is None:
245 return li
246 else:
247 li.append(val)
248
249 def __readDict(self):
250 """
251 Private method to read a Python dictionary.
252
253 @return Python dictionary
254 """
255 d = {}
256 while not self.atEnd():
257 self.readNext()
258 if self.isStartElement():
259 if self.name() == "key":
260 key = self._readBasics()
261 elif self.name() == "value":
262 d[key] = self._readBasics()
263 if self.isEndElement() and self.name() == "dict":
264 self.readNext()
265
266 if self.isEndElement() and self.name() == "dict":
267 return d
268
269 def __readSet(self):
270 """
271 Private method to read a Python set.
272
273 @return Python set
274 """
275 li = []
276 while not self.atEnd():
277 val = self._readBasics()
278 if self.isEndElement() and self.name() == "set" and val is None:
279 return set(li)
280 else:
281 li.append(val)
282
283 def __readFrozenset(self):
284 """
285 Private method to read a Python set.
286
287 @return Python set
288 """
289 li = []
290 while not self.atEnd():
291 val = self._readBasics()
292 if (
293 self.isEndElement() and
294 self.name() == "frozenset" and
295 val is None
296 ):
297 return frozenset(li)
298 else:
299 li.append(val)

eric ide

mercurial