eric7/E5XML/XMLStreamReaderBase.py

branch
eric7
changeset 8312
800c432b34c8
parent 8228
772103b14c18
child 8314
e3642a6a1e71
equal deleted inserted replaced
8311:4e8b98454baa 8312:800c432b34c8
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 eric6s XML stream writers.
8 """
9
10 import pickle # secok
11 import base64
12
13 from PyQt5.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 eric6s 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 att = self.attributes().value(name)
115 if att == "":
116 att = default
117 return att
118
119 def _skipUnknownElement(self):
120 """
121 Protected method to skip over all unknown elements.
122 """
123 if not self.isStartElement():
124 return
125
126 while not self.atEnd():
127 self.readNext()
128 if self.isEndElement():
129 break
130
131 if self.isStartElement():
132 self._skipUnknownElement()
133
134 def _readBasics(self):
135 """
136 Protected method to read an object of a basic Python type.
137
138 @return Python object read
139 """
140 while not self.atEnd():
141 self.readNext()
142 if self.isStartElement():
143 try:
144 if self.name() == "none":
145 val = None
146 elif self.name() in ("int", "long"):
147 val = int(self.readElementText())
148 elif self.name() == "bool":
149 b = self.readElementText()
150 if b == "True":
151 val = True
152 else:
153 val = False
154 elif self.name() == "float":
155 val = float(self.readElementText())
156 elif self.name() == "complex":
157 real, imag = self.readElementText().split()
158 val = float(real) + float(imag) * 1j
159 elif self.name() == "string":
160 val = self.readElementText()
161 elif self.name() == "bytes":
162 by = bytes([int(b) for b in
163 self.readElementText().split(",")])
164 val = by
165 elif self.name() == "bytearray":
166 by = bytearray([int(b) for b in
167 self.readElementText().split(",")])
168 val = by
169 elif self.name() == "tuple":
170 val = self.__readTuple()
171 return val
172 elif self.name() == "list":
173 val = self.__readList()
174 return val
175 elif self.name() == "dict":
176 val = self.__readDict()
177 return val
178 elif self.name() == "set":
179 val = self.__readSet()
180 return val
181 elif self.name() == "frozenset":
182 val = self.__readFrozenset()
183 return val
184 elif self.name() == "pickle":
185 encoding = self.attribute("encoding")
186 if encoding != "base64":
187 self.raiseError(QCoreApplication.translate(
188 "XMLStreamReaderBase",
189 "Pickle data encoding '{0}' is not"
190 " supported.").format(encoding))
191 continue
192 b64 = self.readElementText()
193 pic = base64.b64decode(b64.encode("ASCII"))
194 val = pickle.loads(pic) # secok
195 else:
196 self._skipUnknownElement()
197 except ValueError as err:
198 self.raiseError(str(err))
199 continue
200
201 if self.isEndElement():
202 if self.name() in [
203 "tuple", "list", "dict", "set", "frozenset"]:
204 return None
205 else:
206 return val
207
208 def __readTuple(self):
209 """
210 Private method to read a Python tuple.
211
212 @return Python tuple
213 """
214 li = []
215 while not self.atEnd():
216 val = self._readBasics()
217 if self.isEndElement() and self.name() == "tuple" and val is None:
218 return tuple(li)
219 else:
220 li.append(val)
221
222 def __readList(self):
223 """
224 Private method to read a Python list.
225
226 @return Python list
227 """
228 li = []
229 while not self.atEnd():
230 val = self._readBasics()
231 if self.isEndElement() and self.name() == "list" and val is None:
232 return li
233 else:
234 li.append(val)
235
236 def __readDict(self):
237 """
238 Private method to read a Python dictionary.
239
240 @return Python dictionary
241 """
242 d = {}
243 while not self.atEnd():
244 self.readNext()
245 if self.isStartElement():
246 if self.name() == "key":
247 key = self._readBasics()
248 elif self.name() == "value":
249 d[key] = self._readBasics()
250 if self.isEndElement() and self.name() == "dict":
251 self.readNext()
252
253 if self.isEndElement() and self.name() == "dict":
254 return d
255
256 def __readSet(self):
257 """
258 Private method to read a Python set.
259
260 @return Python set
261 """
262 li = []
263 while not self.atEnd():
264 val = self._readBasics()
265 if self.isEndElement() and self.name() == "set" and val is None:
266 return set(li)
267 else:
268 li.append(val)
269
270 def __readFrozenset(self):
271 """
272 Private method to read a Python set.
273
274 @return Python set
275 """
276 li = []
277 while not self.atEnd():
278 val = self._readBasics()
279 if (
280 self.isEndElement() and
281 self.name() == "frozenset" and
282 val is None
283 ):
284 return frozenset(li)
285 else:
286 li.append(val)

eric ide

mercurial