eric6/E5XML/XMLStreamReaderBase.py

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

eric ide

mercurial