1import os 2import sys 3import traceback 4from _pydev_bundle.pydev_imports import xmlrpclib, _queue, Exec 5from _pydev_bundle._pydev_calltip_util import get_description 6from _pydevd_bundle import pydevd_vars 7from _pydevd_bundle import pydevd_xml 8from _pydevd_bundle.pydevd_constants import (IS_JYTHON, dict_iter_items, NEXT_VALUE_SEPARATOR, get_global_debugger, 9 silence_warnings_decorator) 10from contextlib import contextmanager 11from _pydev_bundle import pydev_log 12from _pydevd_bundle.pydevd_utils import interrupt_main_thread 13 14try: 15 import cStringIO as StringIO # may not always be available @UnusedImport 16except: 17 try: 18 import StringIO # @Reimport 19 except: 20 import io as StringIO 21 22 23# ======================================================================================================================= 24# BaseStdIn 25# ======================================================================================================================= 26class BaseStdIn: 27 28 def __init__(self, original_stdin=sys.stdin, *args, **kwargs): 29 try: 30 self.encoding = sys.stdin.encoding 31 except: 32 # Not sure if it's available in all Python versions... 33 pass 34 self.original_stdin = original_stdin 35 36 try: 37 self.errors = sys.stdin.errors # Who knew? sys streams have an errors attribute! 38 except: 39 # Not sure if it's available in all Python versions... 40 pass 41 42 def readline(self, *args, **kwargs): 43 # sys.stderr.write('Cannot readline out of the console evaluation\n') -- don't show anything 44 # This could happen if the user had done input('enter number).<-- upon entering this, that message would appear, 45 # which is not something we want. 46 return '\n' 47 48 def write(self, *args, **kwargs): 49 pass # not available StdIn (but it can be expected to be in the stream interface) 50 51 def flush(self, *args, **kwargs): 52 pass # not available StdIn (but it can be expected to be in the stream interface) 53 54 def read(self, *args, **kwargs): 55 # in the interactive interpreter, a read and a readline are the same. 56 return self.readline() 57 58 def close(self, *args, **kwargs): 59 pass # expected in StdIn 60 61 def __iter__(self): 62 # BaseStdIn would not be considered as Iterable in Python 3 without explicit `__iter__` implementation 63 return self.original_stdin.__iter__() 64 65 def __getattr__(self, item): 66 # it's called if the attribute wasn't found 67 if hasattr(self.original_stdin, item): 68 return getattr(self.original_stdin, item) 69 raise AttributeError("%s has no attribute %s" % (self.original_stdin, item)) 70 71 72# ======================================================================================================================= 73# StdIn 74# ======================================================================================================================= 75class StdIn(BaseStdIn): 76 ''' 77 Object to be added to stdin (to emulate it as non-blocking while the next line arrives) 78 ''' 79 80 def __init__(self, interpreter, host, client_port, original_stdin=sys.stdin): 81 BaseStdIn.__init__(self, original_stdin) 82 self.interpreter = interpreter 83 self.client_port = client_port 84 self.host = host 85 86 def readline(self, *args, **kwargs): 87 # Ok, callback into the client to get the new input 88 try: 89 server = xmlrpclib.Server('http://%s:%s' % (self.host, self.client_port)) 90 requested_input = server.RequestInput() 91 if not requested_input: 92 return '\n' # Yes, a readline must return something (otherwise we can get an EOFError on the input() call). 93 else: 94 # readline should end with '\n' (not doing so makes IPython 5 remove the last *valid* character). 95 requested_input += '\n' 96 return requested_input 97 except KeyboardInterrupt: 98 raise # Let KeyboardInterrupt go through -- #PyDev-816: Interrupting infinite loop in the Interactive Console 99 except: 100 return '\n' 101 102 def close(self, *args, **kwargs): 103 pass # expected in StdIn 104 105 106#======================================================================================================================= 107# DebugConsoleStdIn 108#======================================================================================================================= 109class DebugConsoleStdIn(BaseStdIn): 110 ''' 111 Object to be added to stdin (to emulate it as non-blocking while the next line arrives) 112 ''' 113 114 def __init__(self, py_db, original_stdin): 115 ''' 116 :param py_db: 117 If None, get_global_debugger() is used. 118 ''' 119 BaseStdIn.__init__(self, original_stdin) 120 self._py_db = py_db 121 self._in_notification = 0 122 123 def __send_input_requested_message(self, is_started): 124 try: 125 py_db = self._py_db 126 if py_db is None: 127 py_db = get_global_debugger() 128 129 if py_db is None: 130 return 131 132 cmd = py_db.cmd_factory.make_input_requested_message(is_started) 133 py_db.writer.add_command(cmd) 134 except Exception: 135 pydev_log.exception() 136 137 @contextmanager 138 def notify_input_requested(self): 139 self._in_notification += 1 140 if self._in_notification == 1: 141 self.__send_input_requested_message(True) 142 try: 143 yield 144 finally: 145 self._in_notification -= 1 146 if self._in_notification == 0: 147 self.__send_input_requested_message(False) 148 149 def readline(self, *args, **kwargs): 150 with self.notify_input_requested(): 151 return self.original_stdin.readline(*args, **kwargs) 152 153 def read(self, *args, **kwargs): 154 with self.notify_input_requested(): 155 return self.original_stdin.read(*args, **kwargs) 156 157 158class CodeFragment: 159 160 def __init__(self, text, is_single_line=True): 161 self.text = text 162 self.is_single_line = is_single_line 163 164 def append(self, code_fragment): 165 self.text = self.text + "\n" + code_fragment.text 166 if not code_fragment.is_single_line: 167 self.is_single_line = False 168 169 170# ======================================================================================================================= 171# BaseInterpreterInterface 172# ======================================================================================================================= 173class BaseInterpreterInterface: 174 175 def __init__(self, mainThread, connect_status_queue=None): 176 self.mainThread = mainThread 177 self.interruptable = False 178 self.exec_queue = _queue.Queue(0) 179 self.buffer = None 180 self.banner_shown = False 181 self.connect_status_queue = connect_status_queue 182 self.mpl_modules_for_patching = {} 183 self.init_mpl_modules_for_patching() 184 185 def build_banner(self): 186 return 'print({0})\n'.format(repr(self.get_greeting_msg())) 187 188 def get_greeting_msg(self): 189 return 'PyDev console: starting.\n' 190 191 def init_mpl_modules_for_patching(self): 192 from pydev_ipython.matplotlibtools import activate_matplotlib, activate_pylab, activate_pyplot 193 self.mpl_modules_for_patching = { 194 "matplotlib": lambda: activate_matplotlib(self.enableGui), 195 "matplotlib.pyplot": activate_pyplot, 196 "pylab": activate_pylab 197 } 198 199 def need_more_for_code(self, source): 200 # PyDev-502: PyDev 3.9 F2 doesn't support backslash continuations 201 202 # Strangely even the IPython console is_complete said it was complete 203 # even with a continuation char at the end. 204 if source.endswith('\\'): 205 return True 206 207 if hasattr(self.interpreter, 'is_complete'): 208 return not self.interpreter.is_complete(source) 209 try: 210 # At this point, it should always be single. 211 # If we don't do this, things as: 212 # 213 # for i in range(10): print(i) 214 # 215 # (in a single line) don't work. 216 # Note that it won't give an error and code will be None (so, it'll 217 # use execMultipleLines in the next call in this case). 218 symbol = 'single' 219 code = self.interpreter.compile(source, '<input>', symbol) 220 except (OverflowError, SyntaxError, ValueError): 221 # Case 1 222 return False 223 if code is None: 224 # Case 2 225 return True 226 227 # Case 3 228 return False 229 230 def need_more(self, code_fragment): 231 if self.buffer is None: 232 self.buffer = code_fragment 233 else: 234 self.buffer.append(code_fragment) 235 236 return self.need_more_for_code(self.buffer.text) 237 238 def create_std_in(self, debugger=None, original_std_in=None): 239 if debugger is None: 240 return StdIn(self, self.host, self.client_port, original_stdin=original_std_in) 241 else: 242 return DebugConsoleStdIn(py_db=debugger, original_stdin=original_std_in) 243 244 def add_exec(self, code_fragment, debugger=None): 245 # In case sys.excepthook called, use original excepthook #PyDev-877: Debug console freezes with Python 3.5+ 246 # (showtraceback does it on python 3.5 onwards) 247 sys.excepthook = sys.__excepthook__ 248 try: 249 original_in = sys.stdin 250 try: 251 help = None 252 if 'pydoc' in sys.modules: 253 pydoc = sys.modules['pydoc'] # Don't import it if it still is not there. 254 255 if hasattr(pydoc, 'help'): 256 # You never know how will the API be changed, so, let's code defensively here 257 help = pydoc.help 258 if not hasattr(help, 'input'): 259 help = None 260 except: 261 # Just ignore any error here 262 pass 263 264 more = False 265 try: 266 sys.stdin = self.create_std_in(debugger, original_in) 267 try: 268 if help is not None: 269 # This will enable the help() function to work. 270 try: 271 try: 272 help.input = sys.stdin 273 except AttributeError: 274 help._input = sys.stdin 275 except: 276 help = None 277 if not self._input_error_printed: 278 self._input_error_printed = True 279 sys.stderr.write('\nError when trying to update pydoc.help.input\n') 280 sys.stderr.write('(help() may not work -- please report this as a bug in the pydev bugtracker).\n\n') 281 traceback.print_exc() 282 283 try: 284 self.start_exec() 285 if hasattr(self, 'debugger'): 286 self.debugger.enable_tracing() 287 288 more = self.do_add_exec(code_fragment) 289 290 if hasattr(self, 'debugger'): 291 self.debugger.disable_tracing() 292 293 self.finish_exec(more) 294 finally: 295 if help is not None: 296 try: 297 try: 298 help.input = original_in 299 except AttributeError: 300 help._input = original_in 301 except: 302 pass 303 304 finally: 305 sys.stdin = original_in 306 except SystemExit: 307 raise 308 except: 309 traceback.print_exc() 310 finally: 311 sys.__excepthook__ = sys.excepthook 312 313 return more 314 315 def do_add_exec(self, codeFragment): 316 ''' 317 Subclasses should override. 318 319 @return: more (True if more input is needed to complete the statement and False if the statement is complete). 320 ''' 321 raise NotImplementedError() 322 323 def get_namespace(self): 324 ''' 325 Subclasses should override. 326 327 @return: dict with namespace. 328 ''' 329 raise NotImplementedError() 330 331 def __resolve_reference__(self, text): 332 """ 333 334 :type text: str 335 """ 336 obj = None 337 if '.' not in text: 338 try: 339 obj = self.get_namespace()[text] 340 except KeyError: 341 pass 342 343 if obj is None: 344 try: 345 obj = self.get_namespace()['__builtins__'][text] 346 except: 347 pass 348 349 if obj is None: 350 try: 351 obj = getattr(self.get_namespace()['__builtins__'], text, None) 352 except: 353 pass 354 355 else: 356 try: 357 last_dot = text.rindex('.') 358 parent_context = text[0:last_dot] 359 res = pydevd_vars.eval_in_context(parent_context, self.get_namespace(), self.get_namespace()) 360 obj = getattr(res, text[last_dot + 1:]) 361 except: 362 pass 363 return obj 364 365 def getDescription(self, text): 366 try: 367 obj = self.__resolve_reference__(text) 368 if obj is None: 369 return '' 370 return get_description(obj) 371 except: 372 return '' 373 374 def do_exec_code(self, code, is_single_line): 375 try: 376 code_fragment = CodeFragment(code, is_single_line) 377 more = self.need_more(code_fragment) 378 if not more: 379 code_fragment = self.buffer 380 self.buffer = None 381 self.exec_queue.put(code_fragment) 382 383 return more 384 except: 385 traceback.print_exc() 386 return False 387 388 def execLine(self, line): 389 return self.do_exec_code(line, True) 390 391 def execMultipleLines(self, lines): 392 if IS_JYTHON: 393 more = False 394 for line in lines.split('\n'): 395 more = self.do_exec_code(line, True) 396 return more 397 else: 398 return self.do_exec_code(lines, False) 399 400 def interrupt(self): 401 self.buffer = None # Also clear the buffer when it's interrupted. 402 try: 403 if self.interruptable: 404 # Fix for #PyDev-500: Console interrupt can't interrupt on sleep 405 interrupt_main_thread(self.mainThread) 406 407 self.finish_exec(False) 408 return True 409 except: 410 traceback.print_exc() 411 return False 412 413 def close(self): 414 sys.exit(0) 415 416 def start_exec(self): 417 self.interruptable = True 418 419 def get_server(self): 420 if getattr(self, 'host', None) is not None: 421 return xmlrpclib.Server('http://%s:%s' % (self.host, self.client_port)) 422 else: 423 return None 424 425 server = property(get_server) 426 427 def ShowConsole(self): 428 server = self.get_server() 429 if server is not None: 430 server.ShowConsole() 431 432 def finish_exec(self, more): 433 self.interruptable = False 434 435 server = self.get_server() 436 437 if server is not None: 438 return server.NotifyFinished(more) 439 else: 440 return True 441 442 def getFrame(self): 443 xml = StringIO.StringIO() 444 hidden_ns = self.get_ipython_hidden_vars_dict() 445 xml.write("<xml>") 446 xml.write(pydevd_xml.frame_vars_to_xml(self.get_namespace(), hidden_ns)) 447 xml.write("</xml>") 448 449 return xml.getvalue() 450 451 @silence_warnings_decorator 452 def getVariable(self, attributes): 453 xml = StringIO.StringIO() 454 xml.write("<xml>") 455 val_dict = pydevd_vars.resolve_compound_var_object_fields(self.get_namespace(), attributes) 456 if val_dict is None: 457 val_dict = {} 458 459 for k, val in dict_iter_items(val_dict): 460 val = val_dict[k] 461 evaluate_full_value = pydevd_xml.should_evaluate_full_value(val) 462 xml.write(pydevd_vars.var_to_xml(val, k, evaluate_full_value=evaluate_full_value)) 463 464 xml.write("</xml>") 465 466 return xml.getvalue() 467 468 def getArray(self, attr, roffset, coffset, rows, cols, format): 469 name = attr.split("\t")[-1] 470 array = pydevd_vars.eval_in_context(name, self.get_namespace(), self.get_namespace()) 471 return pydevd_vars.table_like_struct_to_xml(array, name, roffset, coffset, rows, cols, format) 472 473 def evaluate(self, expression): 474 xml = StringIO.StringIO() 475 xml.write("<xml>") 476 result = pydevd_vars.eval_in_context(expression, self.get_namespace(), self.get_namespace()) 477 xml.write(pydevd_vars.var_to_xml(result, expression)) 478 xml.write("</xml>") 479 return xml.getvalue() 480 481 @silence_warnings_decorator 482 def loadFullValue(self, seq, scope_attrs): 483 """ 484 Evaluate full value for async Console variables in a separate thread and send results to IDE side 485 :param seq: id of command 486 :param scope_attrs: a sequence of variables with their attributes separated by NEXT_VALUE_SEPARATOR 487 (i.e.: obj\tattr1\tattr2NEXT_VALUE_SEPARATORobj2\attr1\tattr2) 488 :return: 489 """ 490 frame_variables = self.get_namespace() 491 var_objects = [] 492 vars = scope_attrs.split(NEXT_VALUE_SEPARATOR) 493 for var_attrs in vars: 494 if '\t' in var_attrs: 495 name, attrs = var_attrs.split('\t', 1) 496 497 else: 498 name = var_attrs 499 attrs = None 500 if name in frame_variables: 501 var_object = pydevd_vars.resolve_var_object(frame_variables[name], attrs) 502 var_objects.append((var_object, name)) 503 else: 504 var_object = pydevd_vars.eval_in_context(name, frame_variables, frame_variables) 505 var_objects.append((var_object, name)) 506 507 from _pydevd_bundle.pydevd_comm import GetValueAsyncThreadConsole 508 py_db = getattr(self, 'debugger', None) 509 510 if py_db is None: 511 py_db = get_global_debugger() 512 513 if py_db is None: 514 from pydevd import PyDB 515 py_db = PyDB() 516 517 t = GetValueAsyncThreadConsole(py_db, self.get_server(), seq, var_objects) 518 t.start() 519 520 def changeVariable(self, attr, value): 521 522 def do_change_variable(): 523 Exec('%s=%s' % (attr, value), self.get_namespace(), self.get_namespace()) 524 525 # Important: it has to be really enabled in the main thread, so, schedule 526 # it to run in the main thread. 527 self.exec_queue.put(do_change_variable) 528 529 def connectToDebugger(self, debuggerPort, debugger_options=None): 530 ''' 531 Used to show console with variables connection. 532 Mainly, monkey-patches things in the debugger structure so that the debugger protocol works. 533 ''' 534 535 if debugger_options is None: 536 debugger_options = {} 537 env_key = "PYDEVD_EXTRA_ENVS" 538 if env_key in debugger_options: 539 for (env_name, value) in dict_iter_items(debugger_options[env_key]): 540 existing_value = os.environ.get(env_name, None) 541 if existing_value: 542 os.environ[env_name] = "%s%c%s" % (existing_value, os.path.pathsep, value) 543 else: 544 os.environ[env_name] = value 545 if env_name == "PYTHONPATH": 546 sys.path.append(value) 547 548 del debugger_options[env_key] 549 550 def do_connect_to_debugger(): 551 try: 552 # Try to import the packages needed to attach the debugger 553 import pydevd 554 from _pydev_imps._pydev_saved_modules import threading 555 except: 556 # This happens on Jython embedded in host eclipse 557 traceback.print_exc() 558 sys.stderr.write('pydevd is not available, cannot connect\n') 559 560 from _pydevd_bundle.pydevd_constants import set_thread_id 561 from _pydev_bundle import pydev_localhost 562 set_thread_id(threading.currentThread(), "console_main") 563 564 VIRTUAL_FRAME_ID = "1" # matches PyStackFrameConsole.java 565 VIRTUAL_CONSOLE_ID = "console_main" # matches PyThreadConsole.java 566 f = FakeFrame() 567 f.f_back = None 568 f.f_globals = {} # As globals=locals here, let's simply let it empty (and save a bit of network traffic). 569 f.f_locals = self.get_namespace() 570 571 self.debugger = pydevd.PyDB() 572 self.debugger.add_fake_frame(thread_id=VIRTUAL_CONSOLE_ID, frame_id=VIRTUAL_FRAME_ID, frame=f) 573 try: 574 pydevd.apply_debugger_options(debugger_options) 575 self.debugger.connect(pydev_localhost.get_localhost(), debuggerPort) 576 self.debugger.prepare_to_run() 577 self.debugger.disable_tracing() 578 except: 579 traceback.print_exc() 580 sys.stderr.write('Failed to connect to target debugger.\n') 581 582 # Register to process commands when idle 583 self.debugrunning = False 584 try: 585 import pydevconsole 586 pydevconsole.set_debug_hook(self.debugger.process_internal_commands) 587 except: 588 traceback.print_exc() 589 sys.stderr.write('Version of Python does not support debuggable Interactive Console.\n') 590 591 # Important: it has to be really enabled in the main thread, so, schedule 592 # it to run in the main thread. 593 self.exec_queue.put(do_connect_to_debugger) 594 595 return ('connect complete',) 596 597 def handshake(self): 598 if self.connect_status_queue is not None: 599 self.connect_status_queue.put(True) 600 return "PyCharm" 601 602 def get_connect_status_queue(self): 603 return self.connect_status_queue 604 605 def hello(self, input_str): 606 # Don't care what the input string is 607 return ("Hello eclipse",) 608 609 def enableGui(self, guiname): 610 ''' Enable the GUI specified in guiname (see inputhook for list). 611 As with IPython, enabling multiple GUIs isn't an error, but 612 only the last one's main loop runs and it may not work 613 ''' 614 615 def do_enable_gui(): 616 from _pydev_bundle.pydev_versioncheck import versionok_for_gui 617 if versionok_for_gui(): 618 try: 619 from pydev_ipython.inputhook import enable_gui 620 enable_gui(guiname) 621 except: 622 sys.stderr.write("Failed to enable GUI event loop integration for '%s'\n" % guiname) 623 traceback.print_exc() 624 elif guiname not in ['none', '', None]: 625 # Only print a warning if the guiname was going to do something 626 sys.stderr.write("PyDev console: Python version does not support GUI event loop integration for '%s'\n" % guiname) 627 # Return value does not matter, so return back what was sent 628 return guiname 629 630 # Important: it has to be really enabled in the main thread, so, schedule 631 # it to run in the main thread. 632 self.exec_queue.put(do_enable_gui) 633 634 def get_ipython_hidden_vars_dict(self): 635 return None 636 637 638# ======================================================================================================================= 639# FakeFrame 640# ======================================================================================================================= 641class FakeFrame: 642 ''' 643 Used to show console with variables connection. 644 A class to be used as a mock of a frame. 645 ''' 646