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