|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2004 - 2010 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing a base class for all of eric5s XML writers. |
|
8 """ |
|
9 |
|
10 import os |
|
11 import pickle |
|
12 import base64 |
|
13 |
|
14 class XMLWriterBase(object): |
|
15 """ |
|
16 Class implementing a base class for all of eric5s XML writers. |
|
17 """ |
|
18 def __init__(self, file): |
|
19 """ |
|
20 Constructor |
|
21 |
|
22 @param file open file (like) object for writing |
|
23 """ |
|
24 self.pf = file |
|
25 |
|
26 self.basics = { |
|
27 type(None) : self._write_none, |
|
28 int : self._write_int, |
|
29 float : self._write_float, |
|
30 complex : self._write_complex, |
|
31 bool : self._write_bool, |
|
32 str : self._write_string, |
|
33 bytes : self._write_bytes, |
|
34 bytearray : self._write_bytearray, |
|
35 tuple : self._write_tuple, |
|
36 list : self._write_list, |
|
37 dict : self._write_dictionary, |
|
38 set : self._write_set, |
|
39 frozenset : self._write_frozenset, |
|
40 } |
|
41 |
|
42 self.NEWPARA = chr(0x2029) |
|
43 self.NEWLINE = chr(0x2028) |
|
44 |
|
45 def _write(self, s, newline = True): |
|
46 """ |
|
47 Protected method used to do the real write operation. |
|
48 |
|
49 @param s string to be written to the XML file |
|
50 @param newline flag indicating a linebreak |
|
51 """ |
|
52 self.pf.write("%s%s" % (s, |
|
53 newline and os.linesep or "")) |
|
54 |
|
55 def writeXML(self): |
|
56 """ |
|
57 Public method to write the XML to the file. |
|
58 """ |
|
59 # write the XML header |
|
60 self._write('<?xml version="1.0" encoding="UTF-8"?>') |
|
61 |
|
62 def escape(self, data, attribute=False): |
|
63 """ |
|
64 Function to escape &, <, and > in a string of data. |
|
65 |
|
66 @param data data to be escaped (string) |
|
67 @param attribute flag indicating escaping is done for an attribute |
|
68 @return the escaped data (string) |
|
69 """ |
|
70 |
|
71 # must do ampersand first |
|
72 data = data.replace("&", "&") |
|
73 data = data.replace(">", ">") |
|
74 data = data.replace("<", "<") |
|
75 if attribute: |
|
76 data = data.replace('"', """) |
|
77 return data |
|
78 |
|
79 def encodedNewLines(self, text): |
|
80 """ |
|
81 Public method to encode newlines and paragraph breaks. |
|
82 |
|
83 @param text text to encode (string or QString) |
|
84 """ |
|
85 return text.replace("\n\n", self.NEWPARA).replace("\n", self.NEWLINE) |
|
86 |
|
87 def _writeBasics(self, pyobject, indent = 0): |
|
88 """ |
|
89 Protected method to dump an object of a basic Python type. |
|
90 |
|
91 @param pyobject object to be dumped |
|
92 @param indent indentation level for prettier output (integer) |
|
93 """ |
|
94 writeMethod = self.basics.get(type(pyobject)) or self._write_unimplemented |
|
95 writeMethod(pyobject, indent) |
|
96 |
|
97 ############################################################################ |
|
98 ## The various writer methods for basic types |
|
99 ############################################################################ |
|
100 |
|
101 def _write_none(self, value, indent): |
|
102 """ |
|
103 Protected method to dump a NoneType object. |
|
104 |
|
105 @param value value to be dumped (None) (ignored) |
|
106 @param indent indentation level for prettier output (integer) |
|
107 """ |
|
108 self._write('%s<none />' % (" " * indent)) |
|
109 |
|
110 def _write_int(self, value, indent): |
|
111 """ |
|
112 Protected method to dump an int object. |
|
113 |
|
114 @param value value to be dumped (integer) |
|
115 @param indent indentation level for prettier output (integer) |
|
116 """ |
|
117 self._write('%s<int>%s</int>' % (" " * indent, value)) |
|
118 |
|
119 def _write_bool(self, value, indent): |
|
120 """ |
|
121 Protected method to dump a bool object. |
|
122 |
|
123 @param value value to be dumped (boolean) |
|
124 @param indent indentation level for prettier output (integer) |
|
125 """ |
|
126 self._write('%s<bool>%s</bool>' % (" " * indent, value)) |
|
127 |
|
128 def _write_float(self, value, indent): |
|
129 """ |
|
130 Protected method to dump a float object. |
|
131 |
|
132 @param value value to be dumped (float) |
|
133 @param indent indentation level for prettier output (integer) |
|
134 """ |
|
135 self._write('%s<float>%s</float>' % (" " * indent, value)) |
|
136 |
|
137 def _write_complex(self, value, indent): |
|
138 """ |
|
139 Protected method to dump a complex object. |
|
140 |
|
141 @param value value to be dumped (complex) |
|
142 @param indent indentation level for prettier output (integer) |
|
143 """ |
|
144 self._write('%s<complex>%s %s</complex>' % \ |
|
145 (" " * indent, value.real, value.imag)) |
|
146 |
|
147 def _write_string(self, value, indent): |
|
148 """ |
|
149 Protected method to dump a str object. |
|
150 |
|
151 @param value value to be dumped (string) |
|
152 @param indent indentation level for prettier output (integer) |
|
153 """ |
|
154 self._write('%s<string>%s</string>' % (" " * indent, self.escape(value))) |
|
155 |
|
156 def _write_bytes(self, value, indent): |
|
157 """ |
|
158 Protected method to dump a bytes object. |
|
159 |
|
160 @param value value to be dumped (bytes) |
|
161 @param indent indentation level for prettier output (integer) |
|
162 """ |
|
163 self._write('%s<bytes>%s</bytes>' % ( |
|
164 " " * indent, ",".join(["%d" % b for b in value]))) |
|
165 |
|
166 def _write_bytearray(self, value, indent): |
|
167 """ |
|
168 Protected method to dump a bytearray object. |
|
169 |
|
170 @param value value to be dumped (bytearray) |
|
171 @param indent indentation level for prettier output (integer) |
|
172 """ |
|
173 self._write('%s<bytearray>%s</bytearray>' % ( |
|
174 " " * indent, ",".join(["%d" % b for b in value]))) |
|
175 |
|
176 def _write_tuple(self, value, indent): |
|
177 """ |
|
178 Protected method to dump a tuple object. |
|
179 |
|
180 @param value value to be dumped (tuple) |
|
181 @param indent indentation level for prettier output (integer) |
|
182 """ |
|
183 self._write('%s<tuple>' % (" " * indent)) |
|
184 nindent = indent + 1 |
|
185 for elem in value: |
|
186 self._writeBasics(elem, nindent) |
|
187 self._write('%s</tuple>' % (" " * indent)) |
|
188 |
|
189 def _write_list(self, value, indent): |
|
190 """ |
|
191 Protected method to dump a list object. |
|
192 |
|
193 @param value value to be dumped (list) |
|
194 @param indent indentation level for prettier output (integer) |
|
195 """ |
|
196 self._write('%s<list>' % (" " * indent)) |
|
197 nindent = indent + 1 |
|
198 for elem in value: |
|
199 self._writeBasics(elem, nindent) |
|
200 self._write('%s</list>' % (" " * indent)) |
|
201 |
|
202 def _write_dictionary(self, value, indent): |
|
203 """ |
|
204 Protected method to dump a dict object. |
|
205 |
|
206 @param value value to be dumped (dictionary) |
|
207 @param indent indentation level for prettier output (integer) |
|
208 """ |
|
209 self._write('%s<dict>' % (" " * indent)) |
|
210 nindent1 = indent + 1 |
|
211 nindent2 = indent + 2 |
|
212 keys = sorted(list(value.keys())) |
|
213 for key in keys: |
|
214 self._write('%s<key>' % (" " * nindent1)) |
|
215 self._writeBasics(key, nindent2) |
|
216 self._write('%s</key>' % (" " * nindent1)) |
|
217 self._write('%s<value>' % (" " * nindent1)) |
|
218 self._writeBasics(value[key], nindent2) |
|
219 self._write('%s</value>' % (" " * nindent1)) |
|
220 self._write('%s</dict>' % (" " * indent)) |
|
221 |
|
222 def _write_set(self, value, indent): |
|
223 """ |
|
224 Protected method to dump a set object. |
|
225 |
|
226 @param value value to be dumped (set) |
|
227 @param indent indentation level for prettier output (integer) |
|
228 """ |
|
229 self._write('%s<set>' % (" " * indent)) |
|
230 nindent = indent + 1 |
|
231 for elem in value: |
|
232 self._writeBasics(elem, nindent) |
|
233 self._write('%s</set>' % (" " * indent)) |
|
234 |
|
235 def _write_frozenset(self, value, indent): |
|
236 """ |
|
237 Protected method to dump a frozenset object. |
|
238 |
|
239 @param value value to be dumped (frozenset) |
|
240 @param indent indentation level for prettier output (integer) |
|
241 """ |
|
242 self._write('%s<frozenset>' % (" " * indent)) |
|
243 nindent = indent + 1 |
|
244 for elem in value: |
|
245 self._writeBasics(elem, nindent) |
|
246 self._write('%s</frozenset>' % (" " * indent)) |
|
247 |
|
248 def _write_unimplemented(self, value, indent): |
|
249 """ |
|
250 Protected method to dump a type, that has no special method. |
|
251 |
|
252 @param value value to be dumped (any pickleable object) |
|
253 @param indent indentation level for prettier output (integer) |
|
254 """ |
|
255 self._write('%s<pickle method="pickle" encoding="base64">%s</pickle>' % \ |
|
256 (" " * indent, str(base64.b64encode(pickle.dumps(value)), "ASCII"))) |