-
-
Notifications
You must be signed in to change notification settings - Fork 240
/
sitecustomize.py
415 lines (349 loc) · 15.4 KB
/
sitecustomize.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
'''
This module will:
- set the default encoding for python so that it'll print_ things correctly to the console.
- change the input() and raw_input() commands to change \r\n or \r into \n
- execute the user site customize -- if available
- change raw_input() and input() to also remove any trailing \r
'''
DEBUG = 0 #0 or 1 because of jython
import sys
encoding = None
IS_PYTHON_3K = 0
try:
if sys.version_info[0] == 3:
IS_PYTHON_3K = 1
except:
#That's OK, not all versions of python have sys.version_info
if DEBUG:
import traceback;traceback.print_exc() #@Reimport
#-----------------------------------------------------------------------------------------------------------------------
#Line buffering
if IS_PYTHON_3K:
#Python 3 has a bug (http://bugs.python.org/issue4705) in which -u doesn't properly make output/input unbuffered
#so, we need to enable that ourselves here.
try:
sys.stdout._line_buffering = True
except:
pass
try:
sys.stderr._line_buffering = True
except:
pass
try:
sys.stdin._line_buffering = True
except:
pass
if not IS_PYTHON_3K: #For Python 3.0, the PYTHONIOENCODING should already treat that correctly.
#-------------------------------------------------------------------------------------------------------------------
#check if the encoding has been specified for this launch...
#set the encoding with the encoding_config file that should've been created
#before launching the last application (it'll be removed after we get its contents)
try:
import os
new_encoding = os.environ.get('PYDEV_CONSOLE_ENCODING')
if new_encoding and new_encoding.strip():
encoding = new_encoding.strip()
if DEBUG:
sys.stdout.write('encoding from env (PYDEV_CONSOLE_ENCODING): %s\n' % (encoding,))
except:
#ok, just ignore it if we couldn't get it
if DEBUG:
import traceback;traceback.print_exc() #@Reimport
#-------------------------------------------------------------------------------------------------------------------
if not encoding:
#Jython
try:
from java.lang import System
except ImportError:
pass
else:
#that's the way that the encoding is specified in WorkbenchEncoding.getWorkbenchDefaultEncoding
encoding = System.getProperty("file.encoding", "")
if DEBUG:
sys.stdout.write('encoding from "file.encoding": %s\n' % (encoding,))
#-------------------------------------------------------------------------------------------------------------------
if not encoding:
#Python: get the default system locale (if possible)
try:
import locale
except ImportError:
if DEBUG:
import traceback;traceback.print_exc() #@Reimport
else:
loc = locale.getdefaultlocale()
if loc[1]:
#ok, default locale is set (if the user didn't specify any encoding, the system default should be used)
encoding = loc[1]
if DEBUG:
sys.stdout.write('encoding from "locale": %s\n' % (encoding,))
#-------------------------------------------------------------------------------------------------------------------
#if unable to get the encoding, the 'default' encoding is UTF-8
if not encoding:
encoding = "UTF-8"
#-------------------------------------------------------------------------------------------------------------------
#and finally, set the encoding
try:
if encoding:
if DEBUG:
sys.stdout.write('Setting default encoding: %s\n' % (encoding,))
sys.setdefaultencoding(encoding) #@UndefinedVariable (it's deleted after the site.py is executed -- so, it's undefined for code-analysis)
except:
#ignore if we cannot set it correctly
if DEBUG:
import traceback;traceback.print_exc() #@Reimport
try:
import org.python.core.PyDictionary #@UnresolvedImport @UnusedImport -- just to check if it could be valid
def DictContains(d, key):
return d.has_key(key)
except:
try:
#Py3k does not have has_key anymore, and older versions don't have __contains__
DictContains = dict.__contains__
except:
try:
DictContains = dict.has_key
except NameError:
def DictContains(d, key):
return d.has_key(key)
#-----------------------------------------------------------------------------------------------------------------------
#now that we've finished the needed pydev sitecustomize, let's run the default one (if available)
#Ok, some weirdness going on in Python 3k: when removing this module from the sys.module to import the 'real'
#sitecustomize, all the variables in this scope become None (as if it was garbage-collected), so, the the reference
#below is now being kept to create a cyclic reference so that it neven dies)
__pydev_sitecustomize_module__ = sys.modules.get('sitecustomize') #A ref to this module
#remove the pydev site customize (and the pythonpath for it)
paths_removed = []
try:
for c in sys.path[:]:
#Pydev controls the whole classpath in Jython already, so, we don't want a a duplicate for
#what we've already added there (this is needed to support Jython 2.5b1 onwards -- otherwise, as
#we added the sitecustomize to the pythonpath and to the classpath, we'd have to remove it from the
#classpath too -- and I don't think there's a way to do that... or not?)
if c.find('pydev_sitecustomize') != -1 or c == '__classpath__' or c == '__pyclasspath__' or \
c == '__classpath__/' or c == '__pyclasspath__/' or c == '__classpath__\\' or c == '__pyclasspath__\\':
sys.path.remove(c)
if c.find('pydev_sitecustomize') == -1:
#We'll re-add any paths removed but the pydev_sitecustomize we added from pydev.
paths_removed.append(c)
if DictContains(sys.modules, 'sitecustomize'):
del sys.modules['sitecustomize'] #this module
except:
#print the error... should never happen (so, always show, and not only on debug)!
import traceback;traceback.print_exc() #@Reimport
else:
#Now, execute the default sitecustomize
try:
import sitecustomize #@UnusedImport
sitecustomize.__pydev_sitecustomize_module__=__pydev_sitecustomize_module__
except:
pass
if not DictContains(sys.modules, 'sitecustomize'):
#If there was no sitecustomize, re-add the pydev sitecustomize (pypy gives a KeyError if it's not there)
sys.modules['sitecustomize'] = __pydev_sitecustomize_module__
try:
if paths_removed:
if sys is None:
import sys
if sys is not None:
#And after executing the default sitecustomize, restore the paths (if we didn't remove it before,
#the import sitecustomize would recurse).
sys.path.extend(paths_removed)
except:
#print the error... should never happen (so, always show, and not only on debug)!
import traceback;traceback.print_exc() #@Reimport
if not IS_PYTHON_3K:
try:
#Redefine input and raw_input only after the original sitecustomize was executed
#(because otherwise, the original raw_input and input would still not be defined)
import __builtin__
original_raw_input = __builtin__.raw_input
original_input = __builtin__.input
def raw_input(prompt=''):
#the original raw_input would only remove a trailing \n, so, at
#this point if we had a \r\n the \r would remain (which is valid for eclipse)
#so, let's remove the remaining \r which python didn't expect.
ret = original_raw_input(prompt)
if ret.endswith('\r'):
return ret[:-1]
return ret
raw_input.__doc__ = original_raw_input.__doc__
def input(prompt=''):
#input must also be rebinded for using the new raw_input defined
return eval(raw_input(prompt))
input.__doc__ = original_input.__doc__
__builtin__.raw_input = raw_input
__builtin__.input = input
except:
#Don't report errors at this stage
if DEBUG:
import traceback;traceback.print_exc() #@Reimport
else:
try:
import builtins #Python 3.0 does not have the __builtin__ module @UnresolvedImport
original_input = builtins.input
def input(prompt=''):
#the original input would only remove a trailing \n, so, at
#this point if we had a \r\n the \r would remain (which is valid for eclipse)
#so, let's remove the remaining \r which python didn't expect.
ret = original_input(prompt)
if ret.endswith('\r'):
return ret[:-1]
return ret
input.__doc__ = original_input.__doc__
builtins.input = input
except:
#Don't report errors at this stage
if DEBUG:
import traceback;traceback.print_exc() #@Reimport
try:
#The original getpass doesn't work from the eclipse console, so, let's put a replacement
#here (note that it'll not go into echo mode in the console, so, what' the user writes
#will actually be seen)
import getpass #@UnresolvedImport
if IS_PYTHON_3K:
def pydev_getpass(msg='Password: '):
return input(msg)
else:
def pydev_getpass(msg='Password: '):
return raw_input(msg)
getpass.getpass = pydev_getpass
except:
#Don't report errors at this stage
if DEBUG:
import traceback;traceback.print_exc() #@Reimport
"""
The UserModuleDeleter and runfile methods are copied from
Spyder and carry their own license agreement.
http://code.google.com/p/spyderlib/source/browse/spyderlib/widgets/externalshell/sitecustomize.py
Spyder License Agreement (MIT License)
--------------------------------------
Copyright (c) 2009-2012 Pierre Raybaut
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
"""
# The following classes and functions are mainly intended to be used from
# an interactive Python session
class UserModuleDeleter(object):
"""
User Module Deleter (UMD) aims at deleting user modules
to force Python to deeply reload them during import
pathlist [list]: blacklist in terms of module path
namelist [list]: blacklist in terms of module name
"""
def __init__(self, namelist=None, pathlist=None):
if namelist is None:
namelist = []
self.namelist = namelist+['sitecustomize']
if pathlist is None:
pathlist = []
self.pathlist = pathlist
try:
# blacklist all files in org.python.pydev/pysrc
import pydev_pysrc, inspect
self.pathlist.append(os.path.dirname(pydev_pysrc.__file__))
except:
pass
self.previous_modules = sys.modules.keys()
def is_module_blacklisted(self, modname, modpath):
for path in [sys.prefix]+self.pathlist:
if modpath.startswith(path):
return True
else:
return set(modname.split('.')) & set(self.namelist)
def run(self, verbose=False):
"""
Del user modules to force Python to deeply reload them
Do not del modules which are considered as system modules, i.e.
modules installed in subdirectories of Python interpreter's binary
Do not del C modules
"""
log = []
for modname, module in sys.modules.items():
if modname not in self.previous_modules:
modpath = getattr(module, '__file__', None)
if modpath is None:
# *module* is a C module that is statically linked into the
# interpreter. There is no way to know its path, so we
# choose to ignore it.
continue
if not self.is_module_blacklisted(modname, modpath):
log.append(modname)
del sys.modules[modname]
if verbose and log:
print("\x1b[4;33m%s\x1b[24m%s\x1b[0m" % ("UMD has deleted",
": "+", ".join(log)))
__umd__ = None
def _get_globals():
"""Return current Python interpreter globals namespace"""
from __main__ import __dict__ as namespace
shell = namespace.get('__ipythonshell__')
if shell is not None and hasattr(shell, 'user_ns'):
# IPython 0.12+ kernel
return shell.user_ns
else:
# Python interpreter
return namespace
return namespace
def runfile(filename, args=None, wdir=None, namespace=None):
"""
Run filename
args: command line arguments (string)
wdir: working directory
"""
try:
if hasattr(filename, 'decode'):
filename = filename.decode('utf-8')
except (UnicodeError, TypeError):
pass
global __umd__
import os
if os.environ.get("PYDEV_UMD_ENABLED", "").lower() == "true":
if __umd__ is None:
namelist = os.environ.get("PYDEV_UMD_NAMELIST", None)
if namelist is not None:
namelist = namelist.split(',')
__umd__ = UserModuleDeleter(namelist=namelist)
else:
verbose = os.environ.get("PYDEV_UMD_VERBOSE", "").lower() == "true"
__umd__.run(verbose=verbose)
if args is not None and not isinstance(args, basestring):
raise TypeError("expected a character buffer object")
if namespace is None:
namespace = _get_globals()
namespace['__file__'] = filename
sys.argv = [filename]
if args is not None:
for arg in args.split():
sys.argv.append(arg)
if wdir is not None:
try:
if hasattr(wdir, 'decode'):
wdir = wdir.decode('utf-8')
except (UnicodeError, TypeError):
pass
os.chdir(wdir)
execfile(filename, namespace)
sys.argv = ['']
namespace.pop('__file__')
if IS_PYTHON_3K:
import builtins
builtins.runfile = runfile
else:
import __builtin__
__builtin__.runfile = runfile