blob: 026fb7f9880c0791df518519516f6db620bf7eab [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
13from pydevd_utils import *
14
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
54
55IS_PYTHON_3K = False
56
57try:
58 if sys.version_info[0] == 3:
59 IS_PYTHON_3K = True
60except:
61 #That's OK, not all versions of python have sys.version_info
62 pass
63
64try:
65 try:
66 if USE_LIB_COPY:
67 import _pydev_xmlrpclib as xmlrpclib
68 else:
69 import xmlrpclib
70 except ImportError:
71 import xmlrpc.client as xmlrpclib
72except ImportError:
73 import _pydev_xmlrpclib as xmlrpclib
74
75try:
76 class ExecState:
77 FIRST_CALL = True
78 PYDEV_CONSOLE_RUN_IN_UI = False #Defines if we should run commands in the UI thread.
79
80 from org.python.pydev.core.uiutils import RunInUiThread #@UnresolvedImport
81 from java.lang import Runnable #@UnresolvedImport
82
83 class Command(Runnable):
84 def __init__(self, interpreter, line):
85 self.interpreter = interpreter
86 self.line = line
87
88 def run(self):
89 if ExecState.FIRST_CALL:
90 ExecState.FIRST_CALL = False
91 sys.stdout.write('\nYou are now in a console within Eclipse.\nUse it with care as it can halt the VM.\n')
92 sys.stdout.write(
93 'Typing a line with "PYDEV_CONSOLE_TOGGLE_RUN_IN_UI"\nwill start executing all the commands in the UI thread.\n\n')
94
95 if self.line == 'PYDEV_CONSOLE_TOGGLE_RUN_IN_UI':
96 ExecState.PYDEV_CONSOLE_RUN_IN_UI = not ExecState.PYDEV_CONSOLE_RUN_IN_UI
97 if ExecState.PYDEV_CONSOLE_RUN_IN_UI:
98 sys.stdout.write(
99 'Running commands in UI mode. WARNING: using sys.stdin (i.e.: calling raw_input()) WILL HALT ECLIPSE.\n')
100 else:
101 sys.stdout.write('No longer running commands in UI mode.\n')
102 self.more = False
103 else:
104 self.more = self.interpreter.push(self.line)
105
106
107 def Sync(runnable):
108 if ExecState.PYDEV_CONSOLE_RUN_IN_UI:
109 return RunInUiThread.sync(runnable)
110 else:
111 return runnable.run()
112
113except:
114 #If things are not there, define a way in which there's no 'real' sync, only the default execution.
115 class Command:
116 def __init__(self, interpreter, line):
117 self.interpreter = interpreter
118 self.line = line
119
120 def run(self):
121 self.more = self.interpreter.push(self.line)
122
123 def Sync(runnable):
124 runnable.run()
125
126try:
127 try:
128 execfile #Not in Py3k
129 except NameError:
130 from pydev_imports import execfile
131
132 __builtin__.execfile = execfile
133
134except:
135 pass
136
137
138#=======================================================================================================================
139# InterpreterInterface
140#=======================================================================================================================
141class InterpreterInterface(BaseInterpreterInterface):
142 '''
143 The methods in this class should be registered in the xml-rpc server.
144 '''
145
146 def __init__(self, host, client_port, mainThread):
147 BaseInterpreterInterface.__init__(self, mainThread)
148 self.client_port = client_port
149 self.host = host
150 self.namespace = {}
151 self.interpreter = InteractiveConsole(self.namespace)
152 self._input_error_printed = False
153
154
155 def doAddExec(self, line):
156 command = Command(self.interpreter, line)
157 Sync(command)
158 return command.more
159
160
161 def getNamespace(self):
162 return self.namespace
163
164
165 def getCompletions(self, text, act_tok):
166 try:
167 from _completer import Completer
168
169 completer = Completer(self.namespace, None)
170 return completer.complete(act_tok)
171 except:
172 import traceback
173
174 traceback.print_exc()
175 return []
176
177 def close(self):
178 sys.exit(0)
179
180 def get_greeting_msg(self):
181 return 'PyDev console: starting.\n'
182
183
184def process_exec_queue(interpreter):
185 while 1:
186 try:
187 try:
188 line = interpreter.exec_queue.get(block=True, timeout=0.05)
189 except _queue.Empty:
190 continue
191
192 if not interpreter.addExec(line): #TODO: think about locks here
193 interpreter.buffer = []
194 except KeyboardInterrupt:
195 interpreter.buffer = []
196 continue
197 except SystemExit:
198 raise
199 except:
200 type, value, tb = sys.exc_info()
201 traceback.print_exception(type, value, tb, file=sys.__stderr__)
202 exit()
203
204
205try:
206 try:
207 exitfunc = sys.exitfunc
208 except AttributeError:
209 exitfunc = None
210 from pydev_ipython_console import InterpreterInterface
211
212 IPYTHON = True
213 if exitfunc is not None:
214 sys.exitfunc = exitfunc
215
216 else:
217 try:
218 delattr(sys, 'exitfunc')
219 except:
220 pass
221except:
222 IPYTHON = False
223 #sys.stderr.write('PyDev console: started.\n')
224 pass #IPython not available, proceed as usual.
225
226#=======================================================================================================================
227# _DoExit
228#=======================================================================================================================
229def _DoExit(*args):
230 '''
231 We have to override the exit because calling sys.exit will only actually exit the main thread,
232 and as we're in a Xml-rpc server, that won't work.
233 '''
234
235 try:
236 import java.lang.System
237
238 java.lang.System.exit(1)
239 except ImportError:
240 if len(args) == 1:
241 os._exit(args[0])
242 else:
243 os._exit(0)
244
245
246def handshake():
247 return "PyCharm"
248
249
250def ipython_editor(interpreter):
251 def editor(file, line):
252 if file is None:
253 file = ""
254 if line is None:
255 line = "-1"
256 interpreter.ipython_editor(file, line)
257
258 return editor
259
260#=======================================================================================================================
261# StartServer
262#=======================================================================================================================
263def start_server(host, port, interpreter):
264 if port == 0:
265 host = ''
266
267 from pydev_imports import SimpleXMLRPCServer
268
269 try:
270 server = SimpleXMLRPCServer((host, port), logRequests=False, allow_none=True)
271
272 except:
273 sys.stderr.write('Error starting server with host: %s, port: %s, client_port: %s\n' % (host, port, client_port))
274 raise
275
276 server.register_function(interpreter.execLine)
277 server.register_function(interpreter.getCompletions)
278 server.register_function(interpreter.getFrame)
279 server.register_function(interpreter.getVariable)
280 server.register_function(interpreter.changeVariable)
281 server.register_function(interpreter.getDescription)
282 server.register_function(interpreter.close)
283 server.register_function(interpreter.interrupt)
284 server.register_function(handshake)
285
286 if IPYTHON:
287 try:
288 interpreter.interpreter.ipython.hooks.editor = ipython_editor(interpreter)
289 except:
290 pass
291
292 if port == 0:
293 (h, port) = server.socket.getsockname()
294
295 print(port)
296 print(client_port)
297
298
299 sys.stderr.write(interpreter.get_greeting_msg())
300
301 server.serve_forever()
302
303 return server
304
305
306def StartServer(host, port, client_port):
307 #replace exit (see comments on method)
308 #note that this does not work in jython!!! (sys method can't be replaced).
309 sys.exit = _DoExit
310
311 interpreter = InterpreterInterface(host, client_port, threading.currentThread())
312
313 server_thread = threading.Thread(target=start_server,
314 name='ServerThread',
315 args=(host, port, interpreter))
316 server_thread.setDaemon(True)
317 server_thread.start()
318
319 process_exec_queue(interpreter)
320
321
322def get_interpreter():
323 try:
324 interpreterInterface = getattr(__builtin__, 'interpreter')
325 except AttributeError:
326 interpreterInterface = InterpreterInterface(None, None, threading.currentThread())
327 setattr(__builtin__, 'interpreter', interpreterInterface)
328
329 return interpreterInterface
330
331
332def get_completions(text, token, globals, locals):
333 interpreterInterface = get_interpreter()
334
335 interpreterInterface.interpreter.update(globals, locals)
336
337 return interpreterInterface.getCompletions(text, token)
338
339def get_frame():
340 return interpreterInterface.getFrame()
341
342def exec_expression(expression, globals, locals):
343 interpreterInterface = get_interpreter()
344
345 interpreterInterface.interpreter.update(globals, locals)
346
347 res = interpreterInterface.needMore(None, expression)
348
349 if res:
350 return True
351
352 interpreterInterface.addExec(expression)
353
354 return False
355
356
357def read_line(s):
358 ret = ''
359
360 while True:
361 c = s.recv(1)
362
363 if c == '\n' or c == '':
364 break
365 else:
366 ret += c
367
368 return ret
369
370# Debugger integration
371
372class ConsoleWriter(InteractiveInterpreter):
373 skip = 0
374
375 def __init__(self, locals=None):
376 InteractiveInterpreter.__init__(self, locals)
377
378 def write(self, data):
379 #if (data.find("global_vars") == -1 and data.find("pydevd") == -1):
380 if self.skip > 0:
381 self.skip -= 1
382 else:
383 if data == "Traceback (most recent call last):\n":
384 self.skip = 1
385 sys.stderr.write(data)
386
387def consoleExec(thread_id, frame_id, expression):
388 """returns 'False' in case expression is partialy correct
389 """
390 frame = pydevd_vars.findFrame(thread_id, frame_id)
391
392 expression = str(expression.replace('@LINE@', '\n'))
393
394 #Not using frame.f_globals because of https://sourceforge.net/tracker2/?func=detail&aid=2541355&group_id=85796&atid=577329
395 #(Names not resolved in generator expression in method)
396 #See message: http://mail.python.org/pipermail/python-list/2009-January/526522.html
397 updated_globals = {}
398 updated_globals.update(frame.f_globals)
399 updated_globals.update(frame.f_locals) #locals later because it has precedence over the actual globals
400
401 if IPYTHON:
402 return exec_expression(expression, updated_globals, frame.f_locals)
403
404 interpreter = ConsoleWriter()
405
406 try:
407 code = compile_command(expression)
408 except (OverflowError, SyntaxError, ValueError):
409 # Case 1
410 interpreter.showsyntaxerror()
411 return False
412
413 if code is None:
414 # Case 2
415 return True
416
417 #Case 3
418
419 try:
420 Exec(code, updated_globals, frame.f_locals)
421
422 except SystemExit:
423 raise
424 except:
425 interpreter.showtraceback()
426
427 return False
428
429#=======================================================================================================================
430# main
431#=======================================================================================================================
432
433
434if __name__ == '__main__':
435 port, client_port = sys.argv[1:3]
436 import pydev_localhost
437
438 if int(port) == 0 and int(client_port) == 0:
439 (h, p) = pydev_localhost.get_socket_name()
440
441 client_port = p
442
443 StartServer(pydev_localhost.get_localhost(), int(port), int(client_port))