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