blob: e8b8d297ff0fdc87bdb75d96c5b13e2d77b973fa [file] [log] [blame]
Tor Norbye3a2425a2013-11-04 10:16:08 -08001try:
2 from code import InteractiveConsole
3except ImportError:
4 from pydevconsole_code_for_ironpython import InteractiveConsole
5
6from code import compile_command
7from code import InteractiveInterpreter
8
9import os
10import sys
11
12from pydevd_constants import USE_LIB_COPY
Tor Norbye8668e1b2013-12-20 09:14:04 -080013from pydevd_constants import IS_JYTHON
Tor Norbye3a2425a2013-11-04 10:16:08 -080014
15if USE_LIB_COPY:
16 import _pydev_threading as threading
17else:
18 import threading
19
20import traceback
21import fix_getpass
22fix_getpass.fixGetpass()
23
24import pydevd_vars
25
26try:
27 from pydevd_exec import Exec
28except:
29 from pydevd_exec2 import Exec
30
31try:
32 if USE_LIB_COPY:
33 import _pydev_Queue as _queue
34 else:
35 import Queue as _queue
36except:
37 import queue as _queue
38
39try:
40 import __builtin__
41except:
42 import builtins as __builtin__
43
44try:
45 False
46 True
47except NameError: # version < 2.3 -- didn't have the True/False builtins
48 import __builtin__
49
50 setattr(__builtin__, 'True', 1) #Python 3.0 does not accept __builtin__.True = 1 in its syntax
51 setattr(__builtin__, 'False', 0)
52
53from pydev_console_utils import BaseInterpreterInterface
Tor Norbye8668e1b2013-12-20 09:14:04 -080054from pydev_console_utils import CodeFragment
Tor Norbye3a2425a2013-11-04 10:16:08 -080055
56IS_PYTHON_3K = False
57
58try:
59 if sys.version_info[0] == 3:
60 IS_PYTHON_3K = True
61except:
62 #That's OK, not all versions of python have sys.version_info
63 pass
64
65try:
66 try:
67 if USE_LIB_COPY:
68 import _pydev_xmlrpclib as xmlrpclib
69 else:
70 import xmlrpclib
71 except ImportError:
72 import xmlrpc.client as xmlrpclib
73except ImportError:
74 import _pydev_xmlrpclib as xmlrpclib
75
Tor Norbye3a2425a2013-11-04 10:16:08 -080076
Tor Norbye8668e1b2013-12-20 09:14:04 -080077class Command:
78 def __init__(self, interpreter, code_fragment):
79 """
80 :type code_fragment: CodeFragment
81 :type interpreter: InteractiveConsole
82 """
83 self.interpreter = interpreter
84 self.code_fragment = code_fragment
85 self.more = None
Tor Norbye3a2425a2013-11-04 10:16:08 -080086
Tor Norbye8668e1b2013-12-20 09:14:04 -080087 @staticmethod
88 def symbol_for_fragment(code_fragment):
89 if code_fragment.is_single_line:
90 symbol = 'single'
Tor Norbye3a2425a2013-11-04 10:16:08 -080091 else:
Tor Norbye8668e1b2013-12-20 09:14:04 -080092 symbol = 'exec' # Jython doesn't support this
93 return symbol
Tor Norbye3a2425a2013-11-04 10:16:08 -080094
Tor Norbye8668e1b2013-12-20 09:14:04 -080095 def run(self):
96 text = self.code_fragment.text
97 symbol = self.symbol_for_fragment(self.code_fragment)
Tor Norbye3a2425a2013-11-04 10:16:08 -080098
Tor Norbye8668e1b2013-12-20 09:14:04 -080099 self.more = self.interpreter.runsource(text, '<input>', symbol)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800100
101try:
102 try:
103 execfile #Not in Py3k
104 except NameError:
105 from pydev_imports import execfile
106
107 __builtin__.execfile = execfile
108
109except:
110 pass
111
112
113#=======================================================================================================================
114# InterpreterInterface
115#=======================================================================================================================
116class InterpreterInterface(BaseInterpreterInterface):
117 '''
118 The methods in this class should be registered in the xml-rpc server.
119 '''
120
121 def __init__(self, host, client_port, mainThread):
122 BaseInterpreterInterface.__init__(self, mainThread)
123 self.client_port = client_port
124 self.host = host
125 self.namespace = {}
126 self.interpreter = InteractiveConsole(self.namespace)
127 self._input_error_printed = False
128
129
Tor Norbye8668e1b2013-12-20 09:14:04 -0800130 def doAddExec(self, codeFragment):
131 command = Command(self.interpreter, codeFragment)
132 command.run()
Tor Norbye3a2425a2013-11-04 10:16:08 -0800133 return command.more
134
135
136 def getNamespace(self):
137 return self.namespace
138
139
140 def getCompletions(self, text, act_tok):
141 try:
142 from _completer import Completer
143
144 completer = Completer(self.namespace, None)
145 return completer.complete(act_tok)
146 except:
147 import traceback
148
149 traceback.print_exc()
150 return []
151
152 def close(self):
153 sys.exit(0)
154
155 def get_greeting_msg(self):
156 return 'PyDev console: starting.\n'
157
158
159def process_exec_queue(interpreter):
160 while 1:
161 try:
162 try:
Tor Norbye8668e1b2013-12-20 09:14:04 -0800163 codeFragment = interpreter.exec_queue.get(block=True, timeout=0.05)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800164 except _queue.Empty:
165 continue
166
Tor Norbye8668e1b2013-12-20 09:14:04 -0800167 more = interpreter.addExec(codeFragment)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800168 except KeyboardInterrupt:
Tor Norbye8668e1b2013-12-20 09:14:04 -0800169 interpreter.buffer = None
Tor Norbye3a2425a2013-11-04 10:16:08 -0800170 continue
171 except SystemExit:
172 raise
173 except:
174 type, value, tb = sys.exc_info()
175 traceback.print_exception(type, value, tb, file=sys.__stderr__)
176 exit()
177
178
179try:
180 try:
181 exitfunc = sys.exitfunc
182 except AttributeError:
183 exitfunc = None
184 from pydev_ipython_console import InterpreterInterface
185
186 IPYTHON = True
187 if exitfunc is not None:
188 sys.exitfunc = exitfunc
189
190 else:
191 try:
192 delattr(sys, 'exitfunc')
193 except:
194 pass
195except:
196 IPYTHON = False
197 #sys.stderr.write('PyDev console: started.\n')
198 pass #IPython not available, proceed as usual.
199
200#=======================================================================================================================
201# _DoExit
202#=======================================================================================================================
203def _DoExit(*args):
204 '''
205 We have to override the exit because calling sys.exit will only actually exit the main thread,
206 and as we're in a Xml-rpc server, that won't work.
207 '''
208
209 try:
210 import java.lang.System
211
212 java.lang.System.exit(1)
213 except ImportError:
214 if len(args) == 1:
215 os._exit(args[0])
216 else:
217 os._exit(0)
218
219
220def handshake():
221 return "PyCharm"
222
223
224def ipython_editor(interpreter):
225 def editor(file, line):
226 if file is None:
227 file = ""
228 if line is None:
229 line = "-1"
230 interpreter.ipython_editor(file, line)
231
232 return editor
233
234#=======================================================================================================================
235# StartServer
236#=======================================================================================================================
237def start_server(host, port, interpreter):
238 if port == 0:
239 host = ''
240
241 from pydev_imports import SimpleXMLRPCServer
242
243 try:
244 server = SimpleXMLRPCServer((host, port), logRequests=False, allow_none=True)
245
246 except:
247 sys.stderr.write('Error starting server with host: %s, port: %s, client_port: %s\n' % (host, port, client_port))
248 raise
249
250 server.register_function(interpreter.execLine)
Tor Norbye8668e1b2013-12-20 09:14:04 -0800251 server.register_function(interpreter.execMultipleLines)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800252 server.register_function(interpreter.getCompletions)
253 server.register_function(interpreter.getFrame)
254 server.register_function(interpreter.getVariable)
255 server.register_function(interpreter.changeVariable)
256 server.register_function(interpreter.getDescription)
257 server.register_function(interpreter.close)
258 server.register_function(interpreter.interrupt)
259 server.register_function(handshake)
260
261 if IPYTHON:
262 try:
263 interpreter.interpreter.ipython.hooks.editor = ipython_editor(interpreter)
264 except:
265 pass
266
267 if port == 0:
268 (h, port) = server.socket.getsockname()
269
270 print(port)
271 print(client_port)
272
273
274 sys.stderr.write(interpreter.get_greeting_msg())
275
276 server.serve_forever()
277
278 return server
279
280
281def StartServer(host, port, client_port):
282 #replace exit (see comments on method)
283 #note that this does not work in jython!!! (sys method can't be replaced).
284 sys.exit = _DoExit
285
286 interpreter = InterpreterInterface(host, client_port, threading.currentThread())
287
288 server_thread = threading.Thread(target=start_server,
289 name='ServerThread',
290 args=(host, port, interpreter))
291 server_thread.setDaemon(True)
292 server_thread.start()
293
294 process_exec_queue(interpreter)
295
296
297def get_interpreter():
298 try:
299 interpreterInterface = getattr(__builtin__, 'interpreter')
300 except AttributeError:
301 interpreterInterface = InterpreterInterface(None, None, threading.currentThread())
302 setattr(__builtin__, 'interpreter', interpreterInterface)
303
304 return interpreterInterface
305
306
307def get_completions(text, token, globals, locals):
308 interpreterInterface = get_interpreter()
309
310 interpreterInterface.interpreter.update(globals, locals)
311
312 return interpreterInterface.getCompletions(text, token)
313
314def get_frame():
315 return interpreterInterface.getFrame()
316
Tor Norbye8668e1b2013-12-20 09:14:04 -0800317def exec_code(code, globals, locals):
Tor Norbye3a2425a2013-11-04 10:16:08 -0800318 interpreterInterface = get_interpreter()
319
320 interpreterInterface.interpreter.update(globals, locals)
321
Tor Norbye8668e1b2013-12-20 09:14:04 -0800322 res = interpreterInterface.needMore(code)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800323
324 if res:
325 return True
326
Tor Norbye8668e1b2013-12-20 09:14:04 -0800327 interpreterInterface.addExec(code)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800328
329 return False
330
331
332def read_line(s):
333 ret = ''
334
335 while True:
336 c = s.recv(1)
337
338 if c == '\n' or c == '':
339 break
340 else:
341 ret += c
342
343 return ret
344
345# Debugger integration
346
347class ConsoleWriter(InteractiveInterpreter):
348 skip = 0
349
350 def __init__(self, locals=None):
351 InteractiveInterpreter.__init__(self, locals)
352
353 def write(self, data):
354 #if (data.find("global_vars") == -1 and data.find("pydevd") == -1):
355 if self.skip > 0:
356 self.skip -= 1
357 else:
358 if data == "Traceback (most recent call last):\n":
359 self.skip = 1
360 sys.stderr.write(data)
361
362def consoleExec(thread_id, frame_id, expression):
363 """returns 'False' in case expression is partialy correct
364 """
365 frame = pydevd_vars.findFrame(thread_id, frame_id)
366
367 expression = str(expression.replace('@LINE@', '\n'))
368
369 #Not using frame.f_globals because of https://sourceforge.net/tracker2/?func=detail&aid=2541355&group_id=85796&atid=577329
370 #(Names not resolved in generator expression in method)
371 #See message: http://mail.python.org/pipermail/python-list/2009-January/526522.html
372 updated_globals = {}
373 updated_globals.update(frame.f_globals)
374 updated_globals.update(frame.f_locals) #locals later because it has precedence over the actual globals
375
376 if IPYTHON:
Tor Norbye8668e1b2013-12-20 09:14:04 -0800377 return exec_code(CodeFragment(expression), updated_globals, frame.f_locals)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800378
379 interpreter = ConsoleWriter()
380
381 try:
382 code = compile_command(expression)
383 except (OverflowError, SyntaxError, ValueError):
384 # Case 1
385 interpreter.showsyntaxerror()
386 return False
387
388 if code is None:
389 # Case 2
390 return True
391
392 #Case 3
393
394 try:
395 Exec(code, updated_globals, frame.f_locals)
396
397 except SystemExit:
398 raise
399 except:
400 interpreter.showtraceback()
401
402 return False
403
404#=======================================================================================================================
405# main
406#=======================================================================================================================
407
408
409if __name__ == '__main__':
410 port, client_port = sys.argv[1:3]
411 import pydev_localhost
412
413 if int(port) == 0 and int(client_port) == 0:
414 (h, p) = pydev_localhost.get_socket_name()
415
416 client_port = p
417
418 StartServer(pydev_localhost.get_localhost(), int(port), int(client_port))