forked from fabioz/PyDev.Debugger
-
Notifications
You must be signed in to change notification settings - Fork 0
/
interpreterInfo.py
264 lines (211 loc) · 7.85 KB
/
interpreterInfo.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
'''
This module was created to get information available in the interpreter, such as libraries,
paths, etc.
what is what:
sys.builtin_module_names: contains the builtin modules embeeded in python (rigth now, we specify all manually).
sys.prefix: A string giving the site-specific directory prefix where the platform independent Python files are installed
format is something as
EXECUTABLE:python.exe|libs@compiled_dlls$builtin_mods
all internal are separated by |
'''
import sys
try:
import os.path
def fully_normalize_path(path):
'''fixes the path so that the format of the path really reflects the directories in the system
'''
return os.path.normpath(path)
join = os.path.join
except: # ImportError or AttributeError.
# See: http://stackoverflow.com/questions/10254353/error-while-installing-jython-for-pydev
def fully_normalize_path(path):
'''fixes the path so that the format of the path really reflects the directories in the system
'''
return path
def join(a, b):
if a.endswith('/') or a.endswith('\\'):
return a + b
return a + '/' + b
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
pass
try:
# Just check if False and True are defined (depends on version, not whether it's jython/python)
False
True
except:
exec ('True, False = 1,0') # An exec is used so that python 3k does not give a syntax error
if sys.platform == "cygwin":
try:
import ctypes # use from the system if available
except ImportError:
sys.path.append(join(sys.path[0], 'third_party/wrapped_for_pydev'))
import ctypes
def native_path(path):
MAX_PATH = 512 # On cygwin NT, its 260 lately, but just need BIG ENOUGH buffer
'''Get the native form of the path, like c:\\Foo for /cygdrive/c/Foo'''
retval = ctypes.create_string_buffer(MAX_PATH)
path = fully_normalize_path(path)
path = tobytes(path)
CCP_POSIX_TO_WIN_A = 0
ctypes.cdll.cygwin1.cygwin_conv_path(CCP_POSIX_TO_WIN_A, path, retval, MAX_PATH)
return retval.value
else:
def native_path(path):
return fully_normalize_path(path)
def __getfilesystemencoding():
'''
Note: there's a copy of this method in _pydev_filesystem_encoding.py
'''
try:
ret = sys.getfilesystemencoding()
if not ret:
raise RuntimeError('Unable to get encoding.')
return ret
except:
try:
# Handle Jython
from java.lang import System # @UnresolvedImport
env = System.getProperty("os.name").lower()
if env.find('win') != -1:
return 'ISO-8859-1' # mbcs does not work on Jython, so, use a (hopefully) suitable replacement
return 'utf-8'
except:
pass
# Only available from 2.3 onwards.
if sys.platform == 'win32':
return 'mbcs'
return 'utf-8'
def getfilesystemencoding():
try:
ret = __getfilesystemencoding()
#Check if the encoding is actually there to be used!
if hasattr('', 'encode'):
''.encode(ret)
if hasattr('', 'decode'):
''.decode(ret)
return ret
except:
return 'utf-8'
file_system_encoding = getfilesystemencoding()
if IS_PYTHON_3K:
unicode_type = str
bytes_type = bytes
else:
unicode_type = unicode
bytes_type = str
def tounicode(s):
if hasattr(s, 'decode'):
if not isinstance(s, unicode_type):
# Depending on the platform variant we may have decode on string or not.
return s.decode(file_system_encoding)
return s
def tobytes(s):
if hasattr(s, 'encode'):
if not isinstance(s, bytes_type):
return s.encode(file_system_encoding)
return s
def toasciimxl(s):
# output for xml without a declared encoding
# As the output is xml, we have to encode chars (< and > are ok as they're not accepted in the filesystem name --
# if it was allowed, we'd have to do things more selectively so that < and > don't get wrongly replaced).
s = s.replace("&", "&")
try:
ret = s.encode('ascii', 'xmlcharrefreplace')
except:
# use workaround
ret = ''
for c in s:
try:
ret += c.encode('ascii')
except:
try:
# Python 2: unicode is a valid identifier
ret += unicode("&#%d;") % ord(c)
except:
# Python 3: a string is already unicode, so, just doing it directly should work.
ret += "&#%d;" % ord(c)
return ret
if __name__ == '__main__':
try:
# just give some time to get the reading threads attached (just in case)
import time
time.sleep(0.1)
except:
pass
try:
executable = tounicode(native_path(sys.executable))
except:
executable = tounicode(sys.executable)
if sys.platform == "cygwin" and not executable.endswith(tounicode('.exe')):
executable += tounicode('.exe')
try:
major = str(sys.version_info[0])
minor = str(sys.version_info[1])
except AttributeError:
# older versions of python don't have version_info
import string
s = string.split(sys.version, ' ')[0]
s = string.split(s, '.')
major = s[0]
minor = s[1]
s = tounicode('%s.%s') % (tounicode(major), tounicode(minor))
contents = [tounicode('<xml>')]
contents.append(tounicode('<version>%s</version>') % (tounicode(s),))
contents.append(tounicode('<executable>%s</executable>') % tounicode(executable))
# this is the new implementation to get the system folders
# (still need to check if it works in linux)
# (previously, we were getting the executable dir, but that is not always correct...)
prefix = tounicode(native_path(sys.prefix))
# print_ 'prefix is', prefix
result = []
path_used = sys.path
try:
path_used = path_used[1:] # Use a copy (and don't include the directory of this script as a path.)
except:
pass # just ignore it...
for p in path_used:
p = tounicode(native_path(p))
try:
import string # to be compatible with older versions
if string.find(p, prefix) == 0: # was startswith
result.append((p, True))
else:
result.append((p, False))
except (ImportError, AttributeError):
# python 3k also does not have it
# jython may not have it (depending on how are things configured)
if p.startswith(prefix): # was startswith
result.append((p, True))
else:
result.append((p, False))
for p, b in result:
if b:
contents.append(tounicode('<lib path="ins">%s</lib>') % (p,))
else:
contents.append(tounicode('<lib path="out">%s</lib>') % (p,))
# no compiled libs
# nor forced libs
for builtinMod in sys.builtin_module_names:
contents.append(tounicode('<forced_lib>%s</forced_lib>') % tounicode(builtinMod))
contents.append(tounicode('</xml>'))
unic = tounicode('\n').join(contents)
inasciixml = toasciimxl(unic)
if IS_PYTHON_3K:
# This is the 'official' way of writing binary output in Py3K (see: http://bugs.python.org/issue4571)
sys.stdout.buffer.write(inasciixml)
else:
sys.stdout.write(inasciixml)
try:
sys.stdout.flush()
sys.stderr.flush()
# and give some time to let it read things (just in case)
import time
time.sleep(0.1)
except:
pass
raise RuntimeError('Ok, this is so that it shows the output (ugly hack for some platforms, so that it releases the output).')