Fix errors and fully support matplotlib interactive mode in run and debug with the...
[idea/community.git] / python / helpers / pydev / pydevconsole.py
1 '''
2 Entry point module to start the interactive console.
3 '''
4 from _pydev_imps._pydev_saved_modules import thread
5 start_new_thread = thread.start_new_thread
6
7 try:
8     from code import InteractiveConsole
9 except ImportError:
10     from _pydevd_bundle.pydevconsole_code_for_ironpython import InteractiveConsole
11
12 from code import compile_command
13 from code import InteractiveInterpreter
14
15 import os
16 import sys
17
18 from _pydev_imps._pydev_saved_modules import threading
19 from _pydevd_bundle.pydevd_constants import dict_iter_items
20
21 import traceback
22 from _pydev_bundle import fix_getpass
23 fix_getpass.fix_getpass()
24
25 from _pydevd_bundle import pydevd_vars, pydevd_save_locals
26
27 from _pydev_bundle.pydev_imports import Exec, _queue
28
29 try:
30     import __builtin__
31 except:
32     import builtins as __builtin__  # @UnresolvedImport
33
34 try:
35     False
36     True
37 except NameError: # version < 2.3 -- didn't have the True/False builtins
38     import __builtin__
39
40     setattr(__builtin__, 'True', 1) #Python 3.0 does not accept __builtin__.True = 1 in its syntax
41     setattr(__builtin__, 'False', 0)
42
43 from _pydev_bundle.pydev_console_utils import BaseInterpreterInterface, BaseStdIn
44 from _pydev_bundle.pydev_console_utils import CodeFragment
45
46 IS_PYTHON_3K = False
47 IS_PY24 = False
48
49 try:
50     if sys.version_info[0] == 3:
51         IS_PYTHON_3K = True
52     elif sys.version_info[0] == 2 and sys.version_info[1] == 4:
53         IS_PY24 = True
54 except:
55     #That's OK, not all versions of python have sys.version_info
56     pass
57
58
59 class Command:
60     def __init__(self, interpreter, code_fragment):
61         """
62         :type code_fragment: CodeFragment
63         :type interpreter: InteractiveConsole
64         """
65         self.interpreter = interpreter
66         self.code_fragment = code_fragment
67         self.more = None
68
69
70     def symbol_for_fragment(code_fragment):
71         if code_fragment.is_single_line:
72             symbol = 'single'
73         else:
74             symbol = 'exec' # Jython doesn't support this
75         return symbol
76     symbol_for_fragment = staticmethod(symbol_for_fragment)
77
78     def run(self):
79         text = self.code_fragment.text
80         symbol = self.symbol_for_fragment(self.code_fragment)
81
82         self.more = self.interpreter.runsource(text, '<input>', symbol)
83
84 try:
85     try:
86         execfile #Not in Py3k
87     except NameError:
88         from _pydev_bundle.pydev_imports import execfile
89
90         __builtin__.execfile = execfile
91 except:
92     pass
93
94 # Pull in runfile, the interface to UMD that wraps execfile
95 from _pydev_bundle.pydev_umd import runfile, _set_globals_function
96 try:
97     import builtins  # @UnresolvedImport
98     builtins.runfile = runfile
99 except:
100     import __builtin__
101     __builtin__.runfile = runfile
102
103
104 #=======================================================================================================================
105 # InterpreterInterface
106 #=======================================================================================================================
107 class InterpreterInterface(BaseInterpreterInterface):
108     '''
109         The methods in this class should be registered in the xml-rpc server.
110     '''
111
112     def __init__(self, host, client_port, mainThread, show_banner=True):
113         BaseInterpreterInterface.__init__(self, mainThread)
114         self.client_port = client_port
115         self.host = host
116         self.namespace = {}
117         self.interpreter = InteractiveConsole(self.namespace)
118         self._input_error_printed = False
119
120
121     def do_add_exec(self, codeFragment):
122         command = Command(self.interpreter, codeFragment)
123         command.run()
124         return command.more
125
126
127     def get_namespace(self):
128         return self.namespace
129
130
131     def getCompletions(self, text, act_tok):
132         try:
133             from _pydev_bundle._pydev_completer import Completer
134
135             completer = Completer(self.namespace, None)
136             return completer.complete(act_tok)
137         except:
138             import traceback
139
140             traceback.print_exc()
141             return []
142
143     def close(self):
144         sys.exit(0)
145
146     def get_greeting_msg(self):
147         return 'PyDev console: starting.\n'
148
149
150 class _ProcessExecQueueHelper:
151     _debug_hook = None
152     _return_control_osc = False
153
154 def set_debug_hook(debug_hook):
155     _ProcessExecQueueHelper._debug_hook = debug_hook
156
157
158 def init_mpl_in_console(interpreter):
159     from pydev_ipython.inputhook import set_return_control_callback
160
161     def return_control():
162         ''' A function that the inputhooks can call (via inputhook.stdin_ready()) to find
163             out if they should cede control and return '''
164         if _ProcessExecQueueHelper._debug_hook:
165             # Some of the input hooks check return control without doing
166             # a single operation, so we don't return True on every
167             # call when the debug hook is in place to allow the GUI to run
168             # XXX: Eventually the inputhook code will have diverged enough
169             # from the IPython source that it will be worthwhile rewriting
170             # it rather than pretending to maintain the old API
171             _ProcessExecQueueHelper._return_control_osc = not _ProcessExecQueueHelper._return_control_osc
172             if _ProcessExecQueueHelper._return_control_osc:
173                 return True
174
175         if not interpreter.exec_queue.empty():
176             return True
177         return False
178
179     set_return_control_callback(return_control)
180
181     from _pydev_bundle.pydev_import_hook import import_hook_manager
182     from pydev_ipython.matplotlibtools import activate_matplotlib, activate_pylab, activate_pyplot
183     import_hook_manager.add_module_name("matplotlib", lambda: activate_matplotlib(interpreter.enableGui))
184     # enable_gui_function in activate_matplotlib should be called in main thread. That's why we call
185     # interpreter.enableGui which put it into the interpreter's exec_queue and executes it in the main thread.
186     import_hook_manager.add_module_name("pylab", activate_pylab)
187     import_hook_manager.add_module_name("pyplot", activate_pyplot)
188
189
190 def process_exec_queue(interpreter):
191     init_mpl_in_console(interpreter)
192     from pydev_ipython.inputhook import get_inputhook
193
194     while 1:
195         # Running the request may have changed the inputhook in use
196         inputhook = get_inputhook()
197
198         if _ProcessExecQueueHelper._debug_hook:
199             _ProcessExecQueueHelper._debug_hook()
200
201         if inputhook:
202             try:
203                 # Note: it'll block here until return_control returns True.
204                 inputhook()
205             except:
206                 import traceback;traceback.print_exc()
207         try:
208             try:
209                 code_fragment = interpreter.exec_queue.get(block=True, timeout=1/20.) # 20 calls/second
210             except _queue.Empty:
211                 continue
212
213             if hasattr(code_fragment, '__call__'):
214                 # It can be a callable (i.e.: something that must run in the main
215                 # thread can be put in the queue for later execution).
216                 code_fragment()
217             else:
218                 more = interpreter.add_exec(code_fragment)
219         except KeyboardInterrupt:
220             interpreter.buffer = None
221             continue
222         except SystemExit:
223             raise
224         except:
225             type, value, tb = sys.exc_info()
226             traceback.print_exception(type, value, tb, file=sys.__stderr__)
227             exit()
228
229
230 if 'IPYTHONENABLE' in os.environ:
231     IPYTHON = os.environ['IPYTHONENABLE'] == 'True'
232 else:
233     IPYTHON = True
234
235 try:
236     try:
237         exitfunc = sys.exitfunc
238     except AttributeError:
239         exitfunc = None
240
241     if IPYTHON:
242         from _pydev_bundle.pydev_ipython_console import InterpreterInterface
243         if exitfunc is not None:
244             sys.exitfunc = exitfunc
245         else:
246             try:
247                 delattr(sys, 'exitfunc')
248             except:
249                 pass
250 except:
251     IPYTHON = False
252     pass
253
254
255 #=======================================================================================================================
256 # _DoExit
257 #=======================================================================================================================
258 def do_exit(*args):
259     '''
260         We have to override the exit because calling sys.exit will only actually exit the main thread,
261         and as we're in a Xml-rpc server, that won't work.
262     '''
263
264     try:
265         import java.lang.System
266
267         java.lang.System.exit(1)
268     except ImportError:
269         if len(args) == 1:
270             os._exit(args[0])
271         else:
272             os._exit(0)
273
274
275 def handshake():
276     return "PyCharm"
277
278
279 #=======================================================================================================================
280 # start_console_server
281 #=======================================================================================================================
282 def start_console_server(host, port, interpreter):
283     if port == 0:
284         host = ''
285
286     #I.e.: supporting the internal Jython version in PyDev to create a Jython interactive console inside Eclipse.
287     from _pydev_bundle.pydev_imports import SimpleXMLRPCServer as XMLRPCServer  #@Reimport
288
289     try:
290         if IS_PY24:
291             server = XMLRPCServer((host, port), logRequests=False)
292         else:
293             server = XMLRPCServer((host, port), logRequests=False, allow_none=True)
294
295     except:
296         sys.stderr.write('Error starting server with host: "%s", port: "%s", client_port: "%s"\n' % (host, port, interpreter.client_port))
297         sys.stderr.flush()
298         raise
299
300     # Tell UMD the proper default namespace
301     _set_globals_function(interpreter.get_namespace)
302
303     server.register_function(interpreter.execLine)
304     server.register_function(interpreter.execMultipleLines)
305     server.register_function(interpreter.getCompletions)
306     server.register_function(interpreter.getFrame)
307     server.register_function(interpreter.getVariable)
308     server.register_function(interpreter.changeVariable)
309     server.register_function(interpreter.getDescription)
310     server.register_function(interpreter.close)
311     server.register_function(interpreter.interrupt)
312     server.register_function(handshake)
313     server.register_function(interpreter.connectToDebugger)
314     server.register_function(interpreter.hello)
315     server.register_function(interpreter.getArray)
316     server.register_function(interpreter.evaluate)
317
318     # Functions for GUI main loop integration
319     server.register_function(interpreter.enableGui)
320
321     if port == 0:
322         (h, port) = server.socket.getsockname()
323
324         print(port)
325         print(interpreter.client_port)
326
327
328     sys.stderr.write(interpreter.get_greeting_msg())
329     sys.stderr.flush()
330
331     while True:
332         try:
333             server.serve_forever()
334         except:
335             # Ugly code to be py2/3 compatible
336             # https://sw-brainwy.rhcloud.com/tracker/PyDev/534:
337             # Unhandled "interrupted system call" error in the pydevconsol.py
338             e = sys.exc_info()[1]
339             retry = False
340             try:
341                 retry = e.args[0] == 4 #errno.EINTR
342             except:
343                 pass
344             if not retry:
345                 raise
346                 # Otherwise, keep on going
347     return server
348
349
350 def start_server(host, port, client_port):
351     #replace exit (see comments on method)
352     #note that this does not work in jython!!! (sys method can't be replaced).
353     sys.exit = do_exit
354
355     interpreter = InterpreterInterface(host, client_port, threading.currentThread())
356
357     start_new_thread(start_console_server,(host, port, interpreter))
358
359     process_exec_queue(interpreter)
360
361
362 def get_ipython_hidden_vars_dict():
363     useful_ipython_vars = ['_', '__']
364
365     try:
366         if IPYTHON and hasattr(__builtin__, 'interpreter'):
367             pydev_interpreter = get_interpreter().interpreter
368             if hasattr(pydev_interpreter, 'ipython') and hasattr(pydev_interpreter.ipython, 'user_ns_hidden'):
369                 user_ns_hidden = pydev_interpreter.ipython.user_ns_hidden
370                 if isinstance(user_ns_hidden, dict):
371                     # Since IPython 2 dict `user_ns_hidden` contains hidden variables and values
372                     user_hidden_dict = user_ns_hidden
373                 else:
374                     # In IPython 1.x `user_ns_hidden` used to be a set with names of hidden variables
375                     user_hidden_dict = dict([(key, val) for key, val in dict_iter_items(pydev_interpreter.ipython.user_ns)
376                                              if key in user_ns_hidden])
377                 return dict([(key, val) for key, val in dict_iter_items(user_hidden_dict) if key not in useful_ipython_vars])
378         return None
379     except Exception:
380         traceback.print_exc()
381         return None
382
383
384 def get_interpreter():
385     try:
386         interpreterInterface = getattr(__builtin__, 'interpreter')
387     except AttributeError:
388         interpreterInterface = InterpreterInterface(None, None, threading.currentThread())
389         setattr(__builtin__, 'interpreter', interpreterInterface)
390         sys.stderr.write(interpreterInterface.get_greeting_msg())
391         sys.stderr.flush()
392
393     return interpreterInterface
394
395
396 def get_completions(text, token, globals, locals):
397     interpreterInterface = get_interpreter()
398
399     interpreterInterface.interpreter.update(globals, locals)
400
401     return interpreterInterface.getCompletions(text, token)
402
403 #===============================================================================
404 # Debugger integration
405 #===============================================================================
406
407 def exec_code(code, globals, locals, debugger):
408     interpreterInterface = get_interpreter()
409     interpreterInterface.interpreter.update(globals, locals)
410
411     res = interpreterInterface.need_more(code)
412
413     if res:
414         return True
415
416     interpreterInterface.add_exec(code, debugger)
417
418     return False
419
420
421
422 class ConsoleWriter(InteractiveInterpreter):
423     skip = 0
424
425     def __init__(self, locals=None):
426         InteractiveInterpreter.__init__(self, locals)
427
428     def write(self, data):
429         #if (data.find("global_vars") == -1 and data.find("pydevd") == -1):
430         if self.skip > 0:
431             self.skip -= 1
432         else:
433             if data == "Traceback (most recent call last):\n":
434                 self.skip = 1
435             sys.stderr.write(data)
436
437     def showsyntaxerror(self, filename=None):
438         """Display the syntax error that just occurred."""
439         #Override for avoid using sys.excepthook PY-12600
440         type, value, tb = sys.exc_info()
441         sys.last_type = type
442         sys.last_value = value
443         sys.last_traceback = tb
444         if filename and type is SyntaxError:
445             # Work hard to stuff the correct filename in the exception
446             try:
447                 msg, (dummy_filename, lineno, offset, line) = value.args
448             except ValueError:
449                 # Not the format we expect; leave it alone
450                 pass
451             else:
452                 # Stuff in the right filename
453                 value = SyntaxError(msg, (filename, lineno, offset, line))
454                 sys.last_value = value
455         list = traceback.format_exception_only(type, value)
456         sys.stderr.write(''.join(list))
457
458     def showtraceback(self):
459         """Display the exception that just occurred."""
460         #Override for avoid using sys.excepthook PY-12600
461         try:
462             type, value, tb = sys.exc_info()
463             sys.last_type = type
464             sys.last_value = value
465             sys.last_traceback = tb
466             tblist = traceback.extract_tb(tb)
467             del tblist[:1]
468             lines = traceback.format_list(tblist)
469             if lines:
470                 lines.insert(0, "Traceback (most recent call last):\n")
471             lines.extend(traceback.format_exception_only(type, value))
472         finally:
473             tblist = tb = None
474         sys.stderr.write(''.join(lines))
475
476 def console_exec(thread_id, frame_id, expression, dbg):
477     """returns 'False' in case expression is partially correct
478     """
479     frame = pydevd_vars.find_frame(thread_id, frame_id)
480
481     expression = str(expression.replace('@LINE@', '\n'))
482
483     #Not using frame.f_globals because of https://sourceforge.net/tracker2/?func=detail&aid=2541355&group_id=85796&atid=577329
484     #(Names not resolved in generator expression in method)
485     #See message: http://mail.python.org/pipermail/python-list/2009-January/526522.html
486     updated_globals = {}
487     updated_globals.update(frame.f_globals)
488     updated_globals.update(frame.f_locals) #locals later because it has precedence over the actual globals
489
490     if IPYTHON:
491         need_more =  exec_code(CodeFragment(expression), updated_globals, frame.f_locals, dbg)
492         if not need_more:
493             pydevd_save_locals.save_locals(frame)
494         return need_more
495
496
497     interpreter = ConsoleWriter()
498
499     try:
500         code = compile_command(expression)
501     except (OverflowError, SyntaxError, ValueError):
502         # Case 1
503         interpreter.showsyntaxerror()
504         return False
505
506     if code is None:
507         # Case 2
508         return True
509
510     #Case 3
511
512     try:
513         Exec(code, updated_globals, frame.f_locals)
514
515     except SystemExit:
516         raise
517     except:
518         interpreter.showtraceback()
519     else:
520         pydevd_save_locals.save_locals(frame)
521     return False
522
523 #=======================================================================================================================
524 # main
525 #=======================================================================================================================
526 if __name__ == '__main__':
527     #Important: don't use this module directly as the __main__ module, rather, import itself as pydevconsole
528     #so that we don't get multiple pydevconsole modules if it's executed directly (otherwise we'd have multiple
529     #representations of its classes).
530     #See: https://sw-brainwy.rhcloud.com/tracker/PyDev/446:
531     #'Variables' and 'Expressions' views stopped working when debugging interactive console
532     import pydevconsole
533     sys.stdin = pydevconsole.BaseStdIn(sys.stdin)
534     port, client_port = sys.argv[1:3]
535     from _pydev_bundle import pydev_localhost
536
537     if int(port) == 0 and int(client_port) == 0:
538         (h, p) = pydev_localhost.get_socket_name()
539
540         client_port = p
541
542     pydevconsole.start_server(pydev_localhost.get_localhost(), int(port), int(client_port))