eric6/Globals/compatibility_fixes.py

branch
without_py2_and_pyqt4
changeset 7197
331569d44b19
parent 7196
ab0a91b82b37
child 7198
684261ef2165
equal deleted inserted replaced
7196:ab0a91b82b37 7197:331569d44b19
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2013 - 2015 Tobias Rzepka <tobias.rzepka@gmail.com>
4 #
5
6 """
7 Module implementing some workarounds to let eric6 run under Python 2.
8 """
9
10
11 import __builtin__ # __IGNORE_EXCEPTION__
12 import codecs
13 import imp
14 import locale
15 import os
16 import sys
17
18 # convert all command line arguments to unicode
19 sys.argv = [arg.decode(locale.getpreferredencoding()) for arg in sys.argv]
20
21 """
22 Improvement for the os.path.join function because the original join doesn't
23 use the correct encoding.
24 """
25 # Save original function for use in joinAsUnicode
26 __join = os.path.join
27 # Flag to disable unicode conversion of join function
28 os.path.join_unicode = True
29
30
31 def joinAsUnicode(*args):
32 """
33 Convert none unicode parameter of the os.path.join into unicode.
34
35 @param args paths which should be joined (str, unicode)
36 @return unicode str of the path (unicode)
37 """
38 if os.path.join_unicode:
39 convArgs = []
40 for arg in args:
41 if isinstance(arg, str):
42 arg = arg.decode(locale.getpreferredencoding(), 'replace')
43 convArgs.append(arg)
44 return __join(*convArgs)
45 else:
46 return __join(*args)
47
48 # Replace os.path.join with unicode aware version
49 os.path.join = joinAsUnicode
50
51 """
52 Improvement for the imp.load_source and imp.find_module functions because the
53 originals doesn't use the correct encoding.
54 """
55 # Save original function for use in load_sourceAsStr and find_moduleAsStr
56 __load_source = imp.load_source
57 __find_module = imp.find_module
58
59
60 def load_sourceAsStr(*args):
61 """
62 Convert none str parameter of the imp.load_source into str.
63
64 @param args (str, unicode)
65 @return list of args converted to str (list)
66 """
67 convArgs = []
68 for arg in args:
69 if isinstance(arg, unicode):
70 arg = arg.encode(sys.getfilesystemencoding(), 'strict')
71 convArgs.append(arg)
72 return __load_source(*convArgs)
73
74
75 def find_moduleAsStr(*args):
76 """
77 Convert none str parameter of the imp.find_module into str.
78
79 @param args (str, unicode)
80 @return list of args converted to str (list)
81 """
82 convArgs = []
83 for arg in args:
84 if isinstance(arg, unicode):
85 arg = arg.encode(sys.getfilesystemencoding(), 'strict')
86 convArgs.append(arg)
87 return __find_module(*convArgs)
88
89 # Replace imp.load_source and imp.find_module with unicode aware version
90 imp.load_source = load_sourceAsStr
91 imp.find_module = find_moduleAsStr
92
93 """
94 Improvement for the sys.path list because some other functions doesn't expect
95 unicode in the sys.path list.
96 """
97
98
99 class PlainStrList(list):
100 """
101 Keep track that all added paths to sys.path are str.
102 """
103 def __init__(self, *args):
104 """
105 Constructor
106
107 @param args list of paths to start with (list)
108 """
109 super(PlainStrList, self).__init__()
110 self.extend(list(args))
111
112 def __convert(self, element):
113 """
114 Private method to convert unicode to file system encoding.
115
116 @param element to convert from unicode to file system encoding (any)
117 @return converted element
118 """
119 if isinstance(element, unicode):
120 # Throw exception if it can't be converted, otherwise exception
121 # could occur somewhere else
122 element = element.encode(sys.getfilesystemencoding(), 'strict')
123 return element
124
125 def __setitem__(self, idx, value):
126 """
127 Special method to overwrite a specific list item.
128
129 @param idx index of the item (int)
130 @param value the new value (any)
131 """
132 super(PlainStrList, self).__setitem__(idx, self.__convert(value))
133
134 def insert(self, idx, value):
135 """
136 Public method to insert a specific list item.
137
138 @param idx index of the item (int)
139 @param value the new value (any)
140 """
141 super(PlainStrList, self).insert(idx, self.__convert(value))
142
143
144 # insert a conversion function from unicode to str at sys.path access
145 sys.path = PlainStrList(*sys.path)
146
147 """
148 The open function and File class simulates the open behaviour of Python3.
149
150 The Eric6 used features are emulated only. The not emulated features
151 should throw a NotImplementedError exception.
152 """
153
154
155 def open(filein, mode='r', buffering=-1, encoding=None,
156 errors=None, newline=None, closefd=True):
157 """
158 Replacement for the build in open function.
159
160 @param filein filename or file descriptor (string)
161 @keyparam mode access mode (string)
162 @keyparam buffering size of the read buffer (string)
163 @keyparam encoding character encoding for reading/ writing (string)
164 @keyparam errors behavior for the character encoding ('strict',
165 'explicit', ...) (string)
166 @keyparam newline controls how universal newlines works (string)
167 @keyparam closefd close underlying file descriptor if given as file
168 parameter (boolean)
169 @return Returns the new file object
170 """
171 return File(filein, mode, buffering, encoding, errors, newline, closefd)
172
173
174 class File(file): # __IGNORE_WARNING__
175 """
176 Facade for the original file class.
177 """
178 def __init__(self, filein, mode='r', buffering=-1,
179 encoding=None, errors=None, newline=None, closefd=True):
180 """
181 Constructor
182
183 It checks for unimplemented parameters.
184
185 @param filein filename or file descriptor (string)
186 @keyparam mode access mode (string)
187 @keyparam buffering size of the read buffer (string)
188 @keyparam encoding character encoding for reading/ writing (string)
189 @keyparam errors behavior for the character encoding ('strict',
190 'explicit', ...) (string)
191 @keyparam newline controls how universal newlines works (string)
192 @keyparam closefd close underlying file descriptor if given as file
193 parameter (boolean)
194 @exception NotImplementedError for not implemented method parameters
195 """
196 self.__encoding = encoding
197 self.__newline = str(newline)
198 self.__closefd = closefd
199 if newline is not None:
200 if 'r' in mode:
201 raise NotImplementedError
202 else:
203 mode = mode.replace('t', 'b')
204 if 'b' not in mode:
205 mode = mode + 'b'
206
207 if closefd is False:
208 raise NotImplementedError
209
210 if errors is None:
211 self.__errors = 'strict'
212 else:
213 self.__errors = errors
214
215 file.__init__(self, filein, mode, buffering) # __IGNORE_WARNING__
216
217 def read(self, n=-1):
218 """
219 Public method to read n bytes or all if n=-1 from file.
220
221 @keyparam n bytecount or all if n=-1 (int)
222 @return decoded bytes read
223 """
224 txt = super(File, self).read(n)
225 if self.__encoding is None:
226 return txt
227 else:
228 return codecs.decode(txt, self.__encoding)
229
230 def readline(self, limit=-1):
231 """
232 Public method to read one line from file.
233
234 @keyparam limit maximum bytes to read or all if limit=-1 (int)
235 @return decoded line read
236 """
237 txt = super(File, self).readline(limit)
238 if self.__encoding is None:
239 return txt
240 else:
241 return codecs.decode(txt, self.__encoding)
242
243 def readlines(self, hint=-1):
244 """
245 Public method to read all lines from file.
246
247 @keyparam hint maximum bytes to read or all if hint=-1 (int)
248 @return decoded lines read
249 """
250 if self.__encoding is None:
251 return super(File, self).readlines(hint)
252 else:
253 return [codecs.decode(txt, self.__encoding)
254 for txt in super(File, self).readlines(hint)]
255
256 def write(self, txt):
257 """
258 Public method to write given data to file and encode if needed.
259
260 @param txt data to write. (str, bytes)
261 """
262 if self.__encoding is not None:
263 txt = codecs.encode(txt, self.__encoding, self.__errors)
264 elif isinstance(txt, unicode):
265 txt = codecs.encode(txt, 'utf-8', self.__errors)
266
267 if self.__newline in ['\r\n', '\r']:
268 txt = txt.replace('\n', self.__newline)
269
270 super(File, self).write(txt)
271
272 def next(self):
273 """
274 Public method used in an iterator.
275
276 @return decoded data read
277 """
278 txt = super(File, self).next()
279 if self.__encoding is None:
280 return txt
281 else:
282 return codecs.decode(txt, self.__encoding)
283
284 # Inject into the __builtin__ dictionary
285 __builtin__.open = open
286
287 #
288 # eflag: FileType = Python2
289 # eflag: noqa = M702

eric ide

mercurial