1''' 2Entry point module to start the interactive console. 3''' 4from _pydev_imps._pydev_saved_modules import thread, _code 5from _pydevd_bundle.pydevd_constants import IS_JYTHON 6start_new_thread = thread.start_new_thread 7 8try: 9 from code import InteractiveConsole 10except ImportError: 11 from _pydevd_bundle.pydevconsole_code_for_ironpython import InteractiveConsole 12 13compile_command = _code.compile_command 14InteractiveInterpreter = _code.InteractiveInterpreter 15 16import os 17import sys 18 19from _pydev_imps._pydev_saved_modules import threading 20from _pydevd_bundle.pydevd_constants import INTERACTIVE_MODE_AVAILABLE, dict_keys 21 22import traceback 23from _pydev_bundle import pydev_log 24 25from _pydevd_bundle import pydevd_save_locals 26 27from _pydev_bundle.pydev_imports import Exec, _queue 28 29if sys.version_info[0] >= 3: 30 import builtins as __builtin__ 31else: 32 import __builtin__ 33 34from _pydev_bundle.pydev_console_utils import BaseInterpreterInterface, BaseStdIn # @UnusedImport 35from _pydev_bundle.pydev_console_utils import CodeFragment 36 37IS_PYTHON_3_ONWARDS = sys.version_info[0] >= 3 38IS_PY24 = sys.version_info[0] == 2 and sys.version_info[1] == 4 39 40 41class Command: 42 43 def __init__(self, interpreter, code_fragment): 44 """ 45 :type code_fragment: CodeFragment 46 :type interpreter: InteractiveConsole 47 """ 48 self.interpreter = interpreter 49 self.code_fragment = code_fragment 50 self.more = None 51 52 def symbol_for_fragment(code_fragment): 53 if code_fragment.is_single_line: 54 symbol = 'single' 55 else: 56 if IS_JYTHON: 57 symbol = 'single' # Jython doesn't support exec 58 else: 59 symbol = 'exec' 60 return symbol 61 62 symbol_for_fragment = staticmethod(symbol_for_fragment) 63 64 def run(self): 65 text = self.code_fragment.text 66 symbol = self.symbol_for_fragment(self.code_fragment) 67 68 self.more = self.interpreter.runsource(text, '<input>', symbol) 69 70 71try: 72 try: 73 execfile # Not in Py3k 74 except NameError: 75 from _pydev_bundle.pydev_imports import execfile 76 77 __builtin__.execfile = execfile 78except: 79 pass 80 81# Pull in runfile, the interface to UMD that wraps execfile 82from _pydev_bundle.pydev_umd import runfile, _set_globals_function 83if sys.version_info[0] >= 3: 84 __builtin__.runfile = runfile 85else: 86 __builtin__.runfile = runfile 87 88 89#======================================================================================================================= 90# InterpreterInterface 91#======================================================================================================================= 92class InterpreterInterface(BaseInterpreterInterface): 93 ''' 94 The methods in this class should be registered in the xml-rpc server. 95 ''' 96 97 def __init__(self, host, client_port, mainThread, connect_status_queue=None): 98 BaseInterpreterInterface.__init__(self, mainThread, connect_status_queue) 99 self.client_port = client_port 100 self.host = host 101 self.namespace = {} 102 self.interpreter = InteractiveConsole(self.namespace) 103 self._input_error_printed = False 104 105 def do_add_exec(self, codeFragment): 106 command = Command(self.interpreter, codeFragment) 107 command.run() 108 return command.more 109 110 def get_namespace(self): 111 return self.namespace 112 113 def getCompletions(self, text, act_tok): 114 try: 115 from _pydev_bundle._pydev_completer import Completer 116 117 completer = Completer(self.namespace, None) 118 return completer.complete(act_tok) 119 except: 120 pydev_log.exception() 121 return [] 122 123 def close(self): 124 sys.exit(0) 125 126 def get_greeting_msg(self): 127 return 'PyDev console: starting.\n' 128 129 130class _ProcessExecQueueHelper: 131 _debug_hook = None 132 _return_control_osc = False 133 134 135def set_debug_hook(debug_hook): 136 _ProcessExecQueueHelper._debug_hook = debug_hook 137 138 139def activate_mpl_if_already_imported(interpreter): 140 if interpreter.mpl_modules_for_patching: 141 for module in dict_keys(interpreter.mpl_modules_for_patching): 142 if module in sys.modules: 143 activate_function = interpreter.mpl_modules_for_patching.pop(module) 144 activate_function() 145 146 147def init_set_return_control_back(interpreter): 148 from pydev_ipython.inputhook import set_return_control_callback 149 150 def return_control(): 151 ''' A function that the inputhooks can call (via inputhook.stdin_ready()) to find 152 out if they should cede control and return ''' 153 if _ProcessExecQueueHelper._debug_hook: 154 # Some of the input hooks check return control without doing 155 # a single operation, so we don't return True on every 156 # call when the debug hook is in place to allow the GUI to run 157 # XXX: Eventually the inputhook code will have diverged enough 158 # from the IPython source that it will be worthwhile rewriting 159 # it rather than pretending to maintain the old API 160 _ProcessExecQueueHelper._return_control_osc = not _ProcessExecQueueHelper._return_control_osc 161 if _ProcessExecQueueHelper._return_control_osc: 162 return True 163 164 if not interpreter.exec_queue.empty(): 165 return True 166 return False 167 168 set_return_control_callback(return_control) 169 170 171def init_mpl_in_console(interpreter): 172 init_set_return_control_back(interpreter) 173 174 if not INTERACTIVE_MODE_AVAILABLE: 175 return 176 177 activate_mpl_if_already_imported(interpreter) 178 from _pydev_bundle.pydev_import_hook import import_hook_manager 179 for mod in dict_keys(interpreter.mpl_modules_for_patching): 180 import_hook_manager.add_module_name(mod, interpreter.mpl_modules_for_patching.pop(mod)) 181 182 183if sys.platform != 'win32': 184 185 if not hasattr(os, 'kill'): # Jython may not have it. 186 187 def pid_exists(pid): 188 return True 189 190 else: 191 192 def pid_exists(pid): 193 # Note that this function in the face of errors will conservatively consider that 194 # the pid is still running (because we'll exit the current process when it's 195 # no longer running, so, we need to be 100% sure it actually exited). 196 197 import errno 198 if pid == 0: 199 # According to "man 2 kill" PID 0 has a special meaning: 200 # it refers to <<every process in the process group of the 201 # calling process>> so we don't want to go any further. 202 # If we get here it means this UNIX platform *does* have 203 # a process with id 0. 204 return True 205 try: 206 os.kill(pid, 0) 207 except OSError as err: 208 if err.errno == errno.ESRCH: 209 # ESRCH == No such process 210 return False 211 elif err.errno == errno.EPERM: 212 # EPERM clearly means there's a process to deny access to 213 return True 214 else: 215 # According to "man 2 kill" possible error values are 216 # (EINVAL, EPERM, ESRCH) therefore we should never get 217 # here. If we do, although it's an error, consider it 218 # exists (see first comment in this function). 219 return True 220 else: 221 return True 222 223else: 224 225 def pid_exists(pid): 226 # Note that this function in the face of errors will conservatively consider that 227 # the pid is still running (because we'll exit the current process when it's 228 # no longer running, so, we need to be 100% sure it actually exited). 229 import ctypes 230 kernel32 = ctypes.windll.kernel32 231 232 PROCESS_QUERY_INFORMATION = 0x0400 233 PROCESS_QUERY_LIMITED_INFORMATION = 0x1000 234 ERROR_INVALID_PARAMETER = 0x57 235 STILL_ACTIVE = 259 236 237 process = kernel32.OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_QUERY_LIMITED_INFORMATION, 0, pid) 238 if not process: 239 err = kernel32.GetLastError() 240 if err == ERROR_INVALID_PARAMETER: 241 # Means it doesn't exist (pid parameter is wrong). 242 return False 243 244 # There was some unexpected error (such as access denied), so 245 # consider it exists (although it could be something else, but we don't want 246 # to raise any errors -- so, just consider it exists). 247 return True 248 249 try: 250 zero = ctypes.c_int(0) 251 exit_code = ctypes.pointer(zero) 252 253 exit_code_suceeded = kernel32.GetExitCodeProcess(process, exit_code) 254 if not exit_code_suceeded: 255 # There was some unexpected error (such as access denied), so 256 # consider it exists (although it could be something else, but we don't want 257 # to raise any errors -- so, just consider it exists). 258 return True 259 260 elif bool(exit_code.contents.value) and int(exit_code.contents.value) != STILL_ACTIVE: 261 return False 262 finally: 263 kernel32.CloseHandle(process) 264 265 return True 266 267 268def process_exec_queue(interpreter): 269 init_mpl_in_console(interpreter) 270 from pydev_ipython.inputhook import get_inputhook 271 try: 272 kill_if_pid_not_alive = int(os.environ.get('PYDEV_ECLIPSE_PID', '-1')) 273 except: 274 kill_if_pid_not_alive = -1 275 276 while 1: 277 if kill_if_pid_not_alive != -1: 278 if not pid_exists(kill_if_pid_not_alive): 279 exit() 280 281 # Running the request may have changed the inputhook in use 282 inputhook = get_inputhook() 283 284 if _ProcessExecQueueHelper._debug_hook: 285 _ProcessExecQueueHelper._debug_hook() 286 287 if inputhook: 288 try: 289 # Note: it'll block here until return_control returns True. 290 inputhook() 291 except: 292 pydev_log.exception() 293 try: 294 try: 295 code_fragment = interpreter.exec_queue.get(block=True, timeout=1 / 20.) # 20 calls/second 296 except _queue.Empty: 297 continue 298 299 if callable(code_fragment): 300 # It can be a callable (i.e.: something that must run in the main 301 # thread can be put in the queue for later execution). 302 code_fragment() 303 else: 304 more = interpreter.add_exec(code_fragment) 305 except KeyboardInterrupt: 306 interpreter.buffer = None 307 continue 308 except SystemExit: 309 raise 310 except: 311 pydev_log.exception('Error processing queue on pydevconsole.') 312 exit() 313 314 315if 'IPYTHONENABLE' in os.environ: 316 IPYTHON = os.environ['IPYTHONENABLE'] == 'True' 317else: 318 # By default, don't use IPython because occasionally changes 319 # in IPython break pydevd. 320 IPYTHON = False 321 322try: 323 try: 324 exitfunc = sys.exitfunc 325 except AttributeError: 326 exitfunc = None 327 328 if IPYTHON: 329 from _pydev_bundle.pydev_ipython_console import InterpreterInterface 330 if exitfunc is not None: 331 sys.exitfunc = exitfunc 332 else: 333 try: 334 delattr(sys, 'exitfunc') 335 except: 336 pass 337except: 338 IPYTHON = False 339 pass 340 341 342#======================================================================================================================= 343# _DoExit 344#======================================================================================================================= 345def do_exit(*args): 346 ''' 347 We have to override the exit because calling sys.exit will only actually exit the main thread, 348 and as we're in a Xml-rpc server, that won't work. 349 ''' 350 351 try: 352 import java.lang.System 353 354 java.lang.System.exit(1) 355 except ImportError: 356 if len(args) == 1: 357 os._exit(args[0]) 358 else: 359 os._exit(0) 360 361 362#======================================================================================================================= 363# start_console_server 364#======================================================================================================================= 365def start_console_server(host, port, interpreter): 366 try: 367 if port == 0: 368 host = '' 369 370 # I.e.: supporting the internal Jython version in PyDev to create a Jython interactive console inside Eclipse. 371 from _pydev_bundle.pydev_imports import SimpleXMLRPCServer as XMLRPCServer # @Reimport 372 373 try: 374 if IS_PY24: 375 server = XMLRPCServer((host, port), logRequests=False) 376 else: 377 server = XMLRPCServer((host, port), logRequests=False, allow_none=True) 378 379 except: 380 sys.stderr.write('Error starting server with host: "%s", port: "%s", client_port: "%s"\n' % (host, port, interpreter.client_port)) 381 sys.stderr.flush() 382 raise 383 384 # Tell UMD the proper default namespace 385 _set_globals_function(interpreter.get_namespace) 386 387 server.register_function(interpreter.execLine) 388 server.register_function(interpreter.execMultipleLines) 389 server.register_function(interpreter.getCompletions) 390 server.register_function(interpreter.getFrame) 391 server.register_function(interpreter.getVariable) 392 server.register_function(interpreter.changeVariable) 393 server.register_function(interpreter.getDescription) 394 server.register_function(interpreter.close) 395 server.register_function(interpreter.interrupt) 396 server.register_function(interpreter.handshake) 397 server.register_function(interpreter.connectToDebugger) 398 server.register_function(interpreter.hello) 399 server.register_function(interpreter.getArray) 400 server.register_function(interpreter.evaluate) 401 server.register_function(interpreter.ShowConsole) 402 server.register_function(interpreter.loadFullValue) 403 404 # Functions for GUI main loop integration 405 server.register_function(interpreter.enableGui) 406 407 if port == 0: 408 (h, port) = server.socket.getsockname() 409 410 print(port) 411 print(interpreter.client_port) 412 413 while True: 414 try: 415 server.serve_forever() 416 except: 417 # Ugly code to be py2/3 compatible 418 # https://sw-brainwy.rhcloud.com/tracker/PyDev/534: 419 # Unhandled "interrupted system call" error in the pydevconsol.py 420 e = sys.exc_info()[1] 421 retry = False 422 try: 423 retry = e.args[0] == 4 # errno.EINTR 424 except: 425 pass 426 if not retry: 427 raise 428 # Otherwise, keep on going 429 return server 430 except: 431 pydev_log.exception() 432 # Notify about error to avoid long waiting 433 connection_queue = interpreter.get_connect_status_queue() 434 if connection_queue is not None: 435 connection_queue.put(False) 436 437 438def start_server(host, port, client_port): 439 # replace exit (see comments on method) 440 # note that this does not work in jython!!! (sys method can't be replaced). 441 sys.exit = do_exit 442 443 interpreter = InterpreterInterface(host, client_port, threading.current_thread()) 444 445 start_new_thread(start_console_server, (host, port, interpreter)) 446 447 process_exec_queue(interpreter) 448 449 450def get_ipython_hidden_vars(): 451 if IPYTHON and hasattr(__builtin__, 'interpreter'): 452 interpreter = get_interpreter() 453 return interpreter.get_ipython_hidden_vars_dict() 454 455 456def get_interpreter(): 457 try: 458 interpreterInterface = getattr(__builtin__, 'interpreter') 459 except AttributeError: 460 interpreterInterface = InterpreterInterface(None, None, threading.current_thread()) 461 __builtin__.interpreter = interpreterInterface 462 sys.stderr.write(interpreterInterface.get_greeting_msg()) 463 sys.stderr.flush() 464 465 return interpreterInterface 466 467 468def get_completions(text, token, globals, locals): 469 interpreterInterface = get_interpreter() 470 471 interpreterInterface.interpreter.update(globals, locals) 472 473 return interpreterInterface.getCompletions(text, token) 474 475#=============================================================================== 476# Debugger integration 477#=============================================================================== 478 479 480def exec_code(code, globals, locals, debugger): 481 interpreterInterface = get_interpreter() 482 interpreterInterface.interpreter.update(globals, locals) 483 484 res = interpreterInterface.need_more(code) 485 486 if res: 487 return True 488 489 interpreterInterface.add_exec(code, debugger) 490 491 return False 492 493 494class ConsoleWriter(InteractiveInterpreter): 495 skip = 0 496 497 def __init__(self, locals=None): 498 InteractiveInterpreter.__init__(self, locals) 499 500 def write(self, data): 501 # if (data.find("global_vars") == -1 and data.find("pydevd") == -1): 502 if self.skip > 0: 503 self.skip -= 1 504 else: 505 if data == "Traceback (most recent call last):\n": 506 self.skip = 1 507 sys.stderr.write(data) 508 509 def showsyntaxerror(self, filename=None): 510 """Display the syntax error that just occurred.""" 511 # Override for avoid using sys.excepthook PY-12600 512 type, value, tb = sys.exc_info() 513 sys.last_type = type 514 sys.last_value = value 515 sys.last_traceback = tb 516 if filename and type is SyntaxError: 517 # Work hard to stuff the correct filename in the exception 518 try: 519 msg, (dummy_filename, lineno, offset, line) = value.args 520 except ValueError: 521 # Not the format we expect; leave it alone 522 pass 523 else: 524 # Stuff in the right filename 525 value = SyntaxError(msg, (filename, lineno, offset, line)) 526 sys.last_value = value 527 list = traceback.format_exception_only(type, value) 528 sys.stderr.write(''.join(list)) 529 530 def showtraceback(self, *args, **kwargs): 531 """Display the exception that just occurred.""" 532 # Override for avoid using sys.excepthook PY-12600 533 try: 534 type, value, tb = sys.exc_info() 535 sys.last_type = type 536 sys.last_value = value 537 sys.last_traceback = tb 538 tblist = traceback.extract_tb(tb) 539 del tblist[:1] 540 lines = traceback.format_list(tblist) 541 if lines: 542 lines.insert(0, "Traceback (most recent call last):\n") 543 lines.extend(traceback.format_exception_only(type, value)) 544 finally: 545 tblist = tb = None 546 sys.stderr.write(''.join(lines)) 547 548 549def console_exec(thread_id, frame_id, expression, dbg): 550 """returns 'False' in case expression is partially correct 551 """ 552 frame = dbg.find_frame(thread_id, frame_id) 553 554 is_multiline = expression.count('@LINE@') > 1 555 expression = str(expression.replace('@LINE@', '\n')) 556 557 # Not using frame.f_globals because of https://sourceforge.net/tracker2/?func=detail&aid=2541355&group_id=85796&atid=577329 558 # (Names not resolved in generator expression in method) 559 # See message: http://mail.python.org/pipermail/python-list/2009-January/526522.html 560 updated_globals = {} 561 updated_globals.update(frame.f_globals) 562 updated_globals.update(frame.f_locals) # locals later because it has precedence over the actual globals 563 564 if IPYTHON: 565 need_more = exec_code(CodeFragment(expression), updated_globals, frame.f_locals, dbg) 566 if not need_more: 567 pydevd_save_locals.save_locals(frame) 568 return need_more 569 570 interpreter = ConsoleWriter() 571 572 if not is_multiline: 573 try: 574 code = compile_command(expression) 575 except (OverflowError, SyntaxError, ValueError): 576 # Case 1 577 interpreter.showsyntaxerror() 578 return False 579 if code is None: 580 # Case 2 581 return True 582 else: 583 code = expression 584 585 # Case 3 586 587 try: 588 Exec(code, updated_globals, frame.f_locals) 589 590 except SystemExit: 591 raise 592 except: 593 interpreter.showtraceback() 594 else: 595 pydevd_save_locals.save_locals(frame) 596 return False 597 598 599#======================================================================================================================= 600# main 601#======================================================================================================================= 602if __name__ == '__main__': 603 # Important: don't use this module directly as the __main__ module, rather, import itself as pydevconsole 604 # so that we don't get multiple pydevconsole modules if it's executed directly (otherwise we'd have multiple 605 # representations of its classes). 606 # See: https://sw-brainwy.rhcloud.com/tracker/PyDev/446: 607 # 'Variables' and 'Expressions' views stopped working when debugging interactive console 608 import pydevconsole 609 sys.stdin = pydevconsole.BaseStdIn(sys.stdin) 610 port, client_port = sys.argv[1:3] 611 from _pydev_bundle import pydev_localhost 612 613 if int(port) == 0 and int(client_port) == 0: 614 (h, p) = pydev_localhost.get_socket_name() 615 616 client_port = p 617 618 pydevconsole.start_server(pydev_localhost.get_localhost(), int(port), int(client_port)) 619