def start_client(host, port): #replace exit (see comments on method) #note that this does not work in jython!!! (sys method can't be replaced). sys.exit = do_exit from pydev_console.pydev_protocol import PythonConsoleBackendService, PythonConsoleFrontendService enable_thrift_logging() client_service = PythonConsoleFrontendService client, server_transport = make_rpc_client(client_service, host, port) interpreter = InterpreterInterface(threading.current_thread(), rpc_client=client) # we do not need to start the server in a new thread because it does not need to accept a client connection, it already has it # Tell UMD the proper default namespace _set_globals_function(interpreter.get_namespace) server_service = PythonConsoleBackendService # `InterpreterInterface` implements all methods required for the handler server_handler = interpreter start_rpc_server(server_transport, server_service, server_handler) process_exec_queue(interpreter)
def _pydev_stop_at_break(line): frame = sys._getframe(1) # print('pydevd SET TRACING at ', line, 'curr line', frame.f_lineno) t = threading.current_thread() try: additional_info = t.additional_info except: additional_info = set_additional_thread_info(t) if additional_info.is_tracing: return additional_info.is_tracing += 1 try: py_db = get_global_debugger() if py_db is None: return pydev_log.debug("Setting f_trace due to frame eval mode in file: %s on line %s", frame.f_code.co_filename, line) additional_info.trace_suspend_type = 'frame_eval' pydevd_frame_eval_cython_wrapper = sys.modules['_pydevd_frame_eval.pydevd_frame_eval_cython_wrapper'] thread_info = pydevd_frame_eval_cython_wrapper.get_thread_info_py() if thread_info.thread_trace_func is not None: frame.f_trace = thread_info.thread_trace_func else: frame.f_trace = py_db.get_thread_local_trace_func() finally: additional_info.is_tracing -= 1
def add_custom_frame(frame, name, thread_id): ''' It's possible to show paused frames by adding a custom frame through this API (it's intended to be used for coroutines, but could potentially be used for generators too). :param frame: The topmost frame to be shown paused when a thread with thread.ident == thread_id is paused. :param name: The name to be shown for the custom thread in the UI. :param thread_id: The thread id to which this frame is related (must match thread.ident). :return: str Returns the custom thread id which will be used to show the given frame paused. ''' with CustomFramesContainer.custom_frames_lock: curr_thread_id = get_current_thread_id(threading.current_thread()) next_id = CustomFramesContainer._next_frame_id = CustomFramesContainer._next_frame_id + 1 # Note: the frame id kept contains an id and thread information on the thread where the frame was added # so that later on we can check if the frame is from the current thread by doing frame_id.endswith('|'+thread_id). frame_custom_thread_id = '__frame__:%s|%s' % (next_id, curr_thread_id) if DEBUG: sys.stderr.write( 'add_custom_frame: %s (%s) %s %s\n' % (frame_custom_thread_id, get_abs_path_real_path_and_base_from_frame(frame)[-1], frame.f_lineno, frame.f_code.co_name)) CustomFramesContainer.custom_frames[ frame_custom_thread_id] = CustomFrame(name, frame, thread_id) CustomFramesContainer._py_db_command_thread_event.set() return frame_custom_thread_id
def request_stack(self, py_db, seq, thread_id, timeout=.5): # If it's already suspended, get it right away. internal_get_thread_stack = InternalGetThreadStack(seq, thread_id, py_db, set_additional_thread_info, timeout=timeout) if internal_get_thread_stack.can_be_executed_by(get_current_thread_id(threading.current_thread())): internal_get_thread_stack.do_it(py_db) else: py_db.post_internal_command(internal_get_thread_stack, '*')
def request_stack(self, py_db, seq, thread_id, fmt=None, timeout=.5, start_frame=0, levels=0): # If it's already suspended, get it right away. internal_get_thread_stack = InternalGetThreadStack( seq, thread_id, py_db, set_additional_thread_info, fmt=fmt, timeout=timeout, start_frame=start_frame, levels=levels) if internal_get_thread_stack.can_be_executed_by(get_current_thread_id(threading.current_thread())): internal_get_thread_stack.do_it(py_db) else: py_db.post_internal_command(internal_get_thread_stack, '*')
def dump_frames(thread_id): sys.stdout.write('dumping frames\n') if thread_id != get_current_thread_id(threading.current_thread()): raise VariableError("find_frame: must execute on same thread") frame = get_frame() for frame in iter_frames(frame): sys.stdout.write('%s\n' % pickle.dumps(frame))
def _pydev_needs_stop_at_break(line): ''' We separate the functionality into 2 functions so that we can generate a bytecode which generates a spurious line change so that we can do: if _pydev_needs_stop_at_break(): # Set line to line -1 _pydev_stop_at_break() # then, proceed to go to the current line # (which will then trigger a line event). ''' t = threading.current_thread() try: additional_info = t.additional_info except: additional_info = set_additional_thread_info(t) if additional_info.is_tracing: return False additional_info.is_tracing += 1 try: frame = sys._getframe(1) # print('pydev needs stop at break?', line, 'curr line', frame.f_lineno, 'curr trace', frame.f_trace) if frame.f_trace is not None: # i.e.: this frame is already being traced, thus, we don't need to use programmatic breakpoints. return False py_db = get_global_debugger() if py_db is None: return False try: abs_path_real_path_and_base = NORM_PATHS_AND_BASE_CONTAINER[frame.f_code.co_filename] except: abs_path_real_path_and_base = get_abs_path_real_path_and_base_from_frame(frame) canonical_normalized_filename = abs_path_real_path_and_base[1] try: python_breakpoint = py_db.breakpoints[canonical_normalized_filename][line] except: # print("Couldn't find breakpoint in the file %s on line %s" % (frame.f_code.co_filename, line)) # Could be KeyError if line is not there or TypeError if breakpoints_for_file is None. # Note: using catch-all exception for performance reasons (if the user adds a breakpoint # and then removes it after hitting it once, this method added for the programmatic # breakpoint will keep on being called and one of those exceptions will always be raised # here). return False if python_breakpoint: # print('YES') return True finally: additional_info.is_tracing -= 1 return False
def get_interpreter(): try: interpreterInterface = getattr(__builtin__, 'interpreter') except AttributeError: interpreterInterface = InterpreterInterface(None, None, threading.current_thread()) __builtin__.interpreter = interpreterInterface sys.stderr.write(interpreterInterface.get_greeting_msg()) sys.stderr.flush() return interpreterInterface
def start_server(host, port, client_port): # replace exit (see comments on method) # note that this does not work in jython!!! (sys method can't be replaced). sys.exit = do_exit interpreter = InterpreterInterface(host, client_port, threading.current_thread()) start_new_thread(start_console_server, (host, port, interpreter)) process_exec_queue(interpreter)
def new_func(py_db, frame, expression, is_exec): warn_evaluation_timeout = pydevd_constants.PYDEVD_WARN_EVALUATION_TIMEOUT curr_thread = threading.current_thread() def on_warn_evaluation_timeout(): py_db.writer.add_command(py_db.cmd_factory.make_evaluation_timeout_msg( py_db, expression, curr_thread)) timeout_tracker = py_db.timeout_tracker # : :type timeout_tracker: TimeoutTracker with timeout_tracker.call_on_timeout(warn_evaluation_timeout, on_warn_evaluation_timeout): return _run_with_unblock_threads(original_func, py_db, curr_thread, frame, expression, is_exec)
def _pydev_stop_at_break(line): frame = sys._getframe(1) t = threading.current_thread() if t.additional_info.is_tracing: return False t.additional_info.is_tracing = True try: debugger = get_global_debugger() try: abs_path_real_path_and_base = NORM_PATHS_AND_BASE_CONTAINER[ frame.f_code.co_filename] except: abs_path_real_path_and_base = get_abs_path_real_path_and_base_from_frame( frame) filename = abs_path_real_path_and_base[1] breakpoints_for_file = debugger.breakpoints.get(filename) try: python_breakpoint = breakpoints_for_file[line] except KeyError: pydev_log.debug( "Couldn't find breakpoint in the file {} on line {}".format( frame.f_code.co_filename, line)) return if python_breakpoint: pydev_log.debug( "Suspending at breakpoint in file: {} on line {}".format( frame.f_code.co_filename, line)) t.additional_info.trace_suspend_type = 'frame_eval' pydevd_frame_eval_cython_wrapper = sys.modules[ '_pydevd_frame_eval.pydevd_frame_eval_cython_wrapper'] thread_info = pydevd_frame_eval_cython_wrapper.get_thread_info_py() if thread_info.thread_trace_func is not None: frame.f_trace = thread_info.thread_trace_func else: debugger = get_global_debugger() frame.f_trace = debugger.get_thread_local_trace_func() # For bytecode patching issue diagnosis. Can make the debugger really slow. if os.environ.get( 'PYDEVD_TRACE_OPCODES') == 'True' and IS_PY37_OR_GREATER: frame.f_trace_opcodes = True finally: t.additional_info.is_tracing = False
def do_connect_to_debugger(): try: # Try to import the packages needed to attach the debugger import pydevd from _pydev_imps._pydev_saved_modules import threading except: # This happens on Jython embedded in host eclipse traceback.print_exc() sys.stderr.write('pydevd is not available, cannot connect\n') from _pydevd_bundle.pydevd_constants import set_thread_id from _pydev_bundle import pydev_localhost set_thread_id(threading.current_thread(), "console_main") VIRTUAL_FRAME_ID = "1" # matches PyStackFrameConsole.java VIRTUAL_CONSOLE_ID = "console_main" # matches PyThreadConsole.java f = FakeFrame() f.f_back = None f.f_globals = { } # As globals=locals here, let's simply let it empty (and save a bit of network traffic). f.f_locals = self.get_namespace() self.debugger = pydevd.PyDB() self.debugger.add_fake_frame(thread_id=VIRTUAL_CONSOLE_ID, frame_id=VIRTUAL_FRAME_ID, frame=f) try: pydevd.apply_debugger_options(debugger_options) self.debugger.connect(pydev_localhost.get_localhost(), debuggerPort) self.debugger.prepare_to_run() self.debugger.disable_tracing() except: traceback.print_exc() sys.stderr.write('Failed to connect to target debugger.\n') # Register to process commands when idle self.debugrunning = False try: import pydevconsole pydevconsole.set_debug_hook( self.debugger.process_internal_commands) except: traceback.print_exc() sys.stderr.write( 'Version of Python does not support debuggable Interactive Console.\n' )
def _fallback_excepthook(exctype, value, tb): pydev_log.debug( "Handling the uncaught exception in the fallback exception hook") try: debugger = get_global_debugger() if debugger and debugger.break_on_uncaught_exceptions: thread = threading.current_thread() additional_info = getattr(thread, 'additional_info', None) if not thread or additional_info is None: return debugger.disable_tracing() stop_on_unhandled_exception(debugger, thread, additional_info, (exctype, value, tb)) finally: if sys.excepthook != dummy_excepthook: original_excepthook(exctype, value, tb) sys.exit(1)
def suspend_at_builtin_breakpoint(): # used by built-in breakpoint() function appeared in Python 3.7 frame = sys._getframe(3) t = threading.current_thread() if t.additional_info.is_tracing: return False if t.additional_info.pydev_step_cmd == -1: # do not handle breakpoints while stepping, because they're handled by old tracing function t.additional_info.is_tracing = True pydev_log.debug( "Suspending at breakpoint in file: {} on line {}".format( frame.f_code.co_filename, frame.f_lineno)) debugger = get_global_debugger() debugger.set_suspend(t, CMD_SET_BREAK) debugger.do_wait_suspend(t, frame, 'line', None, "frame_eval") frame.f_trace = debugger.get_thread_local_trace_func() t.additional_info.is_tracing = False
def do_connect_to_debugger(): try: # Try to import the packages needed to attach the debugger import pydevd from _pydev_imps._pydev_saved_modules import threading except: # This happens on Jython embedded in host eclipse traceback.print_exc() sys.stderr.write( 'pydevd is not available, cannot connect\n', ) from _pydevd_bundle.pydevd_constants import set_thread_id from _pydev_bundle import pydev_localhost set_thread_id(threading.current_thread(), "console_main") self.orig_find_frame = pydevd_vars.find_frame pydevd_vars.find_frame = self._findFrame self.debugger = pydevd.PyDB() try: pydevd.apply_debugger_options(debugger_options) if debugger_host is None or pydev_localhost.is_localhost( debugger_host): host = pydev_localhost.get_localhost() else: host = debugger_host self.debugger.connect(host, debuggerPort) self.debugger.prepare_to_run() self.debugger.disable_tracing() except: traceback.print_exc() sys.stderr.write('Failed to connect to target debugger.\n') # Register to process commands when idle self.debugrunning = False try: import pydevconsole pydevconsole.set_debug_hook( self.debugger.process_internal_commands) except: traceback.print_exc() sys.stderr.write( 'Version of Python does not support debuggable Interactive Console.\n' )
def run(self): created_pydb_daemon = self.py_db.created_pydb_daemon_threads created_pydb_daemon[self] = 1 try: try: if IS_JYTHON and not isinstance(threading.current_thread(), threading._MainThread): # we shouldn't update sys.modules for the main thread, cause it leads to the second importing 'threading' # module, and the new instance of main thread is created ss = JyCore.PySystemState() # Note: Py.setSystemState() affects only the current thread. JyCore.Py.setSystemState(ss) self._stop_trace() self._on_run() except: if sys is not None and pydev_log_exception is not None: pydev_log_exception() finally: del created_pydb_daemon[self]
def __call__(self): # We monkey-patch the thread creation so that this function is called in the new thread. At this point # we notify of its creation and start tracing it. py_db = get_global_debugger() thread_id = None if py_db is not None: # Note: if this is a thread from threading.py, we're too early in the boostrap process (because we mocked # the start_new_thread internal machinery and thread._bootstrap has not finished), so, the code below needs # to make sure that we use the current thread bound to the original function and not use # threading.current_thread() unless we're sure it's a dummy thread. t = getattr(self.original_func, '__self__', getattr(self.original_func, 'im_self', None)) if not isinstance(t, threading.Thread): # This is not a threading.Thread but a Dummy thread (so, get it as a dummy thread using # currentThread). t = threading.current_thread() if not getattr(t, 'is_pydev_daemon_thread', False): thread_id = get_current_thread_id(t) py_db.notify_thread_created(thread_id, t) _on_set_trace_for_new_thread(py_db) if getattr(py_db, 'thread_analyser', None) is not None: try: from pydevd_concurrency_analyser.pydevd_concurrency_logger import log_new_thread log_new_thread(py_db, t) except: sys.stderr.write( "Failed to detect new thread for visualization") try: ret = self.original_func(*self.args, **self.kwargs) finally: if thread_id is not None: if py_db is not None: # At thread shutdown we only have pydevd-related code running (which shouldn't # be tracked). py_db.disable_tracing() py_db.notify_thread_not_alive(thread_id) return ret
def create_interrupt_this_thread_callback(): ''' The idea here is returning a callback that when called will generate a KeyboardInterrupt in the thread that called this function. If this is the main thread, this means that it'll emulate a Ctrl+C (which may stop I/O and sleep operations). For other threads, this will call PyThreadState_SetAsyncExc to raise a KeyboardInterrupt before the next instruction (so, it won't really interrupt I/O or sleep operations). :return callable: Returns a callback that will interrupt the current thread (this may be called from an auxiliary thread). ''' tid = thread_get_ident() if is_current_thread_main_thread(): main_thread = threading.current_thread() def raise_on_this_thread(): pydev_log.debug('Callback to interrupt main thread.') pydevd_utils.interrupt_main_thread(main_thread) else: # Note: this works in the sense that it can stop some cpu-intensive slow operation, # but we can't really interrupt the thread out of some sleep or I/O operation # (this will only be raised when Python is about to execute the next instruction). def raise_on_this_thread(): if IS_CPYTHON: pydev_log.debug('Interrupt thread: %s', tid) ctypes.pythonapi.PyThreadState_SetAsyncExc( ctypes.c_long(tid), ctypes.py_object(KeyboardInterrupt)) else: pydev_log.debug( 'It is only possible to interrupt non-main threads in CPython.' ) return raise_on_this_thread
def add_custom_frame(frame, name, thread_id): CustomFramesContainer.custom_frames_lock.acquire() try: curr_thread_id = get_current_thread_id(threading.current_thread()) next_id = CustomFramesContainer._next_frame_id = CustomFramesContainer._next_frame_id + 1 # Note: the frame id kept contains an id and thread information on the thread where the frame was added # so that later on we can check if the frame is from the current thread by doing frame_id.endswith('|'+thread_id). frame_id = '__frame__:%s|%s' % (next_id, curr_thread_id) if DEBUG: sys.stderr.write( 'add_custom_frame: %s (%s) %s %s\n' % (frame_id, get_abs_path_real_path_and_base_from_frame(frame)[-1], frame.f_lineno, frame.f_code.co_name)) CustomFramesContainer.custom_frames[frame_id] = CustomFrame( name, frame, thread_id) CustomFramesContainer._py_db_command_thread_event.set() return frame_id finally: CustomFramesContainer.custom_frames_lock.release()
def start_server(port): if port is None: port = 0 # 0. General stuff #replace exit (see comments on method) #note that this does not work in jython!!! (sys method can't be replaced). sys.exit = do_exit from pydev_console.pydev_protocol import PythonConsoleBackendService, PythonConsoleFrontendService enable_thrift_logging() server_service = PythonConsoleBackendService client_service = PythonConsoleFrontendService # 1. Start Python console server # `InterpreterInterface` implements all methods required for `server_handler` interpreter = InterpreterInterface(threading.current_thread()) # Tell UMD the proper default namespace _set_globals_function(interpreter.get_namespace) server_socket = start_rpc_server_and_make_client( '', port, server_service, client_service, create_server_handler_factory(interpreter)) # 2. Print server port for the IDE _, server_port = server_socket.getsockname() print(server_port) # 3. Wait for IDE to connect to the server process_exec_queue(interpreter)
is_module = setup['module'] from _pydev_bundle import pydev_localhost if int(port) == 0 and int(client_port) == 0: (h, p) = pydev_localhost.get_socket_name() client_port = p host = pydev_localhost.get_localhost() #replace exit (see comments on method) #note that this does not work in jython!!! (sys method can't be replaced). sys.exit = skip_successful_exit connect_status_queue = _queue.Queue() interpreter = InterpreterInterface(host, int(client_port), threading.current_thread(), connect_status_queue=connect_status_queue) server_thread = threading.Thread(target=start_console_server, name='ServerThread', args=(host, int(port), interpreter)) server_thread.daemon = True server_thread.start() sys.stdin = StdIn(interpreter, host, client_port, sys.stdin) init_mpl_in_console(interpreter) try: success = connect_status_queue.get(True, 60) if not success: raise ValueError()
def set_trace_in_qt(): from _pydevd_bundle.pydevd_comm import get_global_debugger py_db = get_global_debugger() if py_db is not None: threading.current_thread() # Create the dummy thread for qt. py_db.enable_tracing()
def process_net_command(py_db, cmd_id, seq, text): '''Processes a command received from the Java side @param cmd_id: the id of the command @param seq: the sequence of the command @param text: the text received in the command @note: this method is run as a big switch... after doing some tests, it's not clear whether changing it for a dict id --> function call will have better performance result. A simple test with xrange(10000000) showed that the gains from having a fast access to what should be executed are lost because of the function call in a way that if we had 10 elements in the switch the if..elif are better -- but growing the number of choices makes the solution with the dispatch look better -- so, if this gets more than 20-25 choices at some time, it may be worth refactoring it (actually, reordering the ifs so that the ones used mostly come before probably will give better performance). ''' # print(ID_TO_MEANING[str(cmd_id)], repr(text)) py_db._main_lock.acquire() try: try: cmd = None if cmd_id == CMD_RUN: py_db.ready_to_run = True elif cmd_id == CMD_SET_PROTOCOL: expected = (NetCommand.HTTP_PROTOCOL, NetCommand.QUOTED_LINE_PROTOCOL) text = text.strip() assert text.strip() in expected, 'Protocol (%s) should be one of: %s' % ( text, expected) NetCommand.protocol = text cmd = py_db.cmd_factory.make_protocol_set_message(seq) elif cmd_id == CMD_VERSION: # response is version number # ide_os should be 'WINDOWS' or 'UNIX'. # Default based on server process (although ideally the IDE should # provide it). if IS_WINDOWS: ide_os = 'WINDOWS' else: ide_os = 'UNIX' # Breakpoints can be grouped by 'LINE' or by 'ID'. breakpoints_by = 'LINE' splitted = text.split('\t') if len(splitted) == 1: _local_version = splitted elif len(splitted) == 2: _local_version, ide_os = splitted elif len(splitted) == 3: _local_version, ide_os, breakpoints_by = splitted if breakpoints_by == 'ID': py_db._set_breakpoints_with_id = True else: py_db._set_breakpoints_with_id = False pydevd_file_utils.set_ide_os(ide_os) cmd = py_db.cmd_factory.make_version_message(seq) elif cmd_id == CMD_LIST_THREADS: # response is a list of threads cmd = py_db.cmd_factory.make_list_threads_message(seq) elif cmd_id == CMD_GET_THREAD_STACK: # Receives a thread_id and a given timeout, which is the time we should # wait to the provide the stack if a given thread is still not suspended. if '\t' in text: thread_id, timeout = text.split('\t') timeout = float(timeout) else: thread_id = text timeout = .5 # Default timeout is .5 seconds # If it's already suspended, get it right away. internal_get_thread_stack = InternalGetThreadStack(seq, thread_id, py_db, set_additional_thread_info, timeout=timeout) if internal_get_thread_stack.can_be_executed_by(get_current_thread_id(threading.current_thread())): internal_get_thread_stack.do_it(py_db) else: py_db.post_internal_command(internal_get_thread_stack, '*') elif cmd_id == CMD_THREAD_SUSPEND: # Yes, thread suspend is done at this point, not through an internal command. threads = [] suspend_all = text.strip() == '*' if suspend_all: threads = pydevd_utils.get_non_pydevd_threads() elif text.startswith('__frame__:'): sys.stderr.write("Can't suspend tasklet: %s\n" % (text,)) else: threads = [pydevd_find_thread_by_id(text)] for t in threads: if t is None: continue py_db.set_suspend( t, CMD_THREAD_SUSPEND, suspend_other_threads=suspend_all, is_pause=True, ) # Break here (even if it's suspend all) as py_db.set_suspend will # take care of suspending other threads. break elif cmd_id == CMD_THREAD_RUN: threads = [] if text.strip() == '*': threads = pydevd_utils.get_non_pydevd_threads() elif text.startswith('__frame__:'): sys.stderr.write("Can't make tasklet run: %s\n" % (text,)) else: threads = [pydevd_find_thread_by_id(text)] for t in threads: if t is None: continue additional_info = set_additional_thread_info(t) additional_info.pydev_step_cmd = -1 additional_info.pydev_step_stop = None additional_info.pydev_state = STATE_RUN elif cmd_id == CMD_STEP_INTO or cmd_id == CMD_STEP_OVER or cmd_id == CMD_STEP_RETURN or \ cmd_id == CMD_STEP_INTO_MY_CODE: # we received some command to make a single step t = pydevd_find_thread_by_id(text) if t: thread_id = get_thread_id(t) int_cmd = InternalStepThread(thread_id, cmd_id) py_db.post_internal_command(int_cmd, thread_id) elif text.startswith('__frame__:'): sys.stderr.write("Can't make tasklet step command: %s\n" % (text,)) elif cmd_id == CMD_RUN_TO_LINE or cmd_id == CMD_SET_NEXT_STATEMENT or cmd_id == CMD_SMART_STEP_INTO: # we received some command to make a single step thread_id, line, func_name = text.split('\t', 2) t = pydevd_find_thread_by_id(thread_id) if t: int_cmd = InternalSetNextStatementThread(thread_id, cmd_id, line, func_name) py_db.post_internal_command(int_cmd, thread_id) elif thread_id.startswith('__frame__:'): sys.stderr.write("Can't set next statement in tasklet: %s\n" % (thread_id,)) elif cmd_id == CMD_RELOAD_CODE: # we received some command to make a reload of a module module_name = text.strip() thread_id = '*' # Any thread # Note: not going for the main thread because in this case it'd only do the load # when we stopped on a breakpoint. int_cmd = ReloadCodeCommand(module_name, thread_id) py_db.post_internal_command(int_cmd, thread_id) elif cmd_id == CMD_CHANGE_VARIABLE: # the text is: thread\tstackframe\tFRAME|GLOBAL\tattribute_to_change\tvalue_to_change try: thread_id, frame_id, scope, attr_and_value = text.split('\t', 3) tab_index = attr_and_value.rindex('\t') attr = attr_and_value[0:tab_index].replace('\t', '.') value = attr_and_value[tab_index + 1:] int_cmd = InternalChangeVariable(seq, thread_id, frame_id, scope, attr, value) py_db.post_internal_command(int_cmd, thread_id) except: traceback.print_exc() elif cmd_id == CMD_GET_VARIABLE: # we received some command to get a variable # the text is: thread_id\tframe_id\tFRAME|GLOBAL\tattributes* try: thread_id, frame_id, scopeattrs = text.split('\t', 2) if scopeattrs.find('\t') != -1: # there are attributes beyond scope scope, attrs = scopeattrs.split('\t', 1) else: scope, attrs = (scopeattrs, None) int_cmd = InternalGetVariable(seq, thread_id, frame_id, scope, attrs) py_db.post_internal_command(int_cmd, thread_id) except: traceback.print_exc() elif cmd_id == CMD_GET_ARRAY: # we received some command to get an array variable # the text is: thread_id\tframe_id\tFRAME|GLOBAL\tname\ttemp\troffs\tcoffs\trows\tcols\tformat try: roffset, coffset, rows, cols, format, thread_id, frame_id, scopeattrs = text.split('\t', 7) if scopeattrs.find('\t') != -1: # there are attributes beyond scope scope, attrs = scopeattrs.split('\t', 1) else: scope, attrs = (scopeattrs, None) int_cmd = InternalGetArray(seq, roffset, coffset, rows, cols, format, thread_id, frame_id, scope, attrs) py_db.post_internal_command(int_cmd, thread_id) except: traceback.print_exc() elif cmd_id == CMD_SHOW_RETURN_VALUES: try: show_return_values = text.split('\t')[1] if int(show_return_values) == 1: py_db.show_return_values = True else: if py_db.show_return_values: # We should remove saved return values py_db.remove_return_values_flag = True py_db.show_return_values = False pydev_log.debug("Show return values: %s\n" % py_db.show_return_values) except: traceback.print_exc() elif cmd_id == CMD_LOAD_FULL_VALUE: try: thread_id, frame_id, scopeattrs = text.split('\t', 2) vars = scopeattrs.split(NEXT_VALUE_SEPARATOR) int_cmd = InternalLoadFullValue(seq, thread_id, frame_id, vars) py_db.post_internal_command(int_cmd, thread_id) except: traceback.print_exc() elif cmd_id == CMD_GET_COMPLETIONS: # we received some command to get a variable # the text is: thread_id\tframe_id\tactivation token try: thread_id, frame_id, scope, act_tok = text.split('\t', 3) int_cmd = InternalGetCompletions(seq, thread_id, frame_id, act_tok) py_db.post_internal_command(int_cmd, thread_id) except: traceback.print_exc() elif cmd_id == CMD_GET_DESCRIPTION: try: thread_id, frame_id, expression = text.split('\t', 2) int_cmd = InternalGetDescription(seq, thread_id, frame_id, expression) py_db.post_internal_command(int_cmd, thread_id) except: traceback.print_exc() elif cmd_id == CMD_GET_FRAME: thread_id, frame_id, scope = text.split('\t', 2) int_cmd = InternalGetFrame(seq, thread_id, frame_id) py_db.post_internal_command(int_cmd, thread_id) elif cmd_id == CMD_SET_BREAK: # func name: 'None': match anything. Empty: match global, specified: only method context. # command to add some breakpoint. # text is file\tline. Add to breakpoints dictionary suspend_policy = "NONE" # Can be 'NONE' or 'ALL' is_logpoint = False hit_condition = None if py_db._set_breakpoints_with_id: try: try: breakpoint_id, type, file, line, func_name, condition, expression, hit_condition, is_logpoint, suspend_policy = text.split('\t', 9) except ValueError: # not enough values to unpack # No suspend_policy passed (use default). breakpoint_id, type, file, line, func_name, condition, expression, hit_condition, is_logpoint = text.split('\t', 8) is_logpoint = is_logpoint == 'True' except ValueError: # not enough values to unpack breakpoint_id, type, file, line, func_name, condition, expression = text.split('\t', 6) breakpoint_id = int(breakpoint_id) line = int(line) # We must restore new lines and tabs as done in # AbstractDebugTarget.breakpointAdded condition = condition.replace("@_@NEW_LINE_CHAR@_@", '\n').\ replace("@_@TAB_CHAR@_@", '\t').strip() expression = expression.replace("@_@NEW_LINE_CHAR@_@", '\n').\ replace("@_@TAB_CHAR@_@", '\t').strip() else: # Note: this else should be removed after PyCharm migrates to setting # breakpoints by id (and ideally also provides func_name). type, file, line, func_name, suspend_policy, condition, expression = text.split('\t', 6) # If we don't have an id given for each breakpoint, consider # the id to be the line. breakpoint_id = line = int(line) condition = condition.replace("@_@NEW_LINE_CHAR@_@", '\n'). \ replace("@_@TAB_CHAR@_@", '\t').strip() expression = expression.replace("@_@NEW_LINE_CHAR@_@", '\n'). \ replace("@_@TAB_CHAR@_@", '\t').strip() if not IS_PY3K: # In Python 3, the frame object will have unicode for the file, whereas on python 2 it has a byte-array encoded with the filesystem encoding. file = file.encode(file_system_encoding) file = pydevd_file_utils.norm_file_to_server(file) if not pydevd_file_utils.exists(file): sys.stderr.write('pydev debugger: warning: trying to add breakpoint'\ ' to file that does not exist: %s (will have no effect)\n' % (file,)) sys.stderr.flush() if condition is not None and (len(condition) <= 0 or condition == "None"): condition = None if expression is not None and (len(expression) <= 0 or expression == "None"): expression = None if hit_condition is not None and (len(hit_condition) <= 0 or hit_condition == "None"): hit_condition = None if type == 'python-line': breakpoint = LineBreakpoint(line, condition, func_name, expression, suspend_policy, hit_condition=hit_condition, is_logpoint=is_logpoint) breakpoints = py_db.breakpoints file_to_id_to_breakpoint = py_db.file_to_id_to_line_breakpoint supported_type = True else: result = None plugin = py_db.get_plugin_lazy_init() if plugin is not None: result = plugin.add_breakpoint('add_line_breakpoint', py_db, type, file, line, condition, expression, func_name, hit_condition=hit_condition, is_logpoint=is_logpoint) if result is not None: supported_type = True breakpoint, breakpoints = result file_to_id_to_breakpoint = py_db.file_to_id_to_plugin_breakpoint else: supported_type = False if not supported_type: raise NameError(type) if DebugInfoHolder.DEBUG_TRACE_BREAKPOINTS > 0: pydev_log.debug('Added breakpoint:%s - line:%s - func_name:%s\n' % (file, line, func_name.encode('utf-8'))) sys.stderr.flush() if file in file_to_id_to_breakpoint: id_to_pybreakpoint = file_to_id_to_breakpoint[file] else: id_to_pybreakpoint = file_to_id_to_breakpoint[file] = {} id_to_pybreakpoint[breakpoint_id] = breakpoint py_db.consolidate_breakpoints(file, id_to_pybreakpoint, breakpoints) if py_db.plugin is not None: py_db.has_plugin_line_breaks = py_db.plugin.has_line_breaks() py_db.on_breakpoints_changed() elif cmd_id == CMD_REMOVE_BREAK: #command to remove some breakpoint #text is type\file\tid. Remove from breakpoints dictionary breakpoint_type, file, breakpoint_id = text.split('\t', 2) if not IS_PY3K: # In Python 3, the frame object will have unicode for the file, whereas on python 2 it has a byte-array encoded with the filesystem encoding. file = file.encode(file_system_encoding) file = pydevd_file_utils.norm_file_to_server(file) try: breakpoint_id = int(breakpoint_id) except ValueError: pydev_log.error('Error removing breakpoint. Expected breakpoint_id to be an int. Found: %s' % (breakpoint_id,)) else: file_to_id_to_breakpoint = None if breakpoint_type == 'python-line': breakpoints = py_db.breakpoints file_to_id_to_breakpoint = py_db.file_to_id_to_line_breakpoint elif py_db.get_plugin_lazy_init() is not None: result = py_db.plugin.get_breakpoints(py_db, breakpoint_type) if result is not None: file_to_id_to_breakpoint = py_db.file_to_id_to_plugin_breakpoint breakpoints = result if file_to_id_to_breakpoint is None: pydev_log.error('Error removing breakpoint. Cant handle breakpoint of type %s' % breakpoint_type) else: try: id_to_pybreakpoint = file_to_id_to_breakpoint.get(file, {}) if DebugInfoHolder.DEBUG_TRACE_BREAKPOINTS > 0: existing = id_to_pybreakpoint[breakpoint_id] sys.stderr.write('Removed breakpoint:%s - line:%s - func_name:%s (id: %s)\n' % ( file, existing.line, existing.func_name.encode('utf-8'), breakpoint_id)) del id_to_pybreakpoint[breakpoint_id] py_db.consolidate_breakpoints(file, id_to_pybreakpoint, breakpoints) if py_db.plugin is not None: py_db.has_plugin_line_breaks = py_db.plugin.has_line_breaks() except KeyError: pydev_log.error("Error removing breakpoint: Breakpoint id not found: %s id: %s. Available ids: %s\n" % ( file, breakpoint_id, dict_keys(id_to_pybreakpoint))) py_db.on_breakpoints_changed(removed=True) elif cmd_id == CMD_EVALUATE_EXPRESSION or cmd_id == CMD_EXEC_EXPRESSION: #command to evaluate the given expression #text is: thread\tstackframe\tLOCAL\texpression temp_name = "" try: thread_id, frame_id, scope, expression, trim, temp_name = text.split('\t', 5) except ValueError: thread_id, frame_id, scope, expression, trim = text.split('\t', 4) int_cmd = InternalEvaluateExpression(seq, thread_id, frame_id, expression, cmd_id == CMD_EXEC_EXPRESSION, int(trim) == 1, temp_name) py_db.post_internal_command(int_cmd, thread_id) elif cmd_id == CMD_CONSOLE_EXEC: #command to exec expression in console, in case expression is only partially valid 'False' is returned #text is: thread\tstackframe\tLOCAL\texpression thread_id, frame_id, scope, expression = text.split('\t', 3) int_cmd = InternalConsoleExec(seq, thread_id, frame_id, expression) py_db.post_internal_command(int_cmd, thread_id) elif cmd_id == CMD_SET_PY_EXCEPTION: # Command which receives set of exceptions on which user wants to break the debugger # text is: # # break_on_uncaught; # break_on_caught; # skip_on_exceptions_thrown_in_same_context; # ignore_exceptions_thrown_in_lines_with_ignore_exception; # ignore_libraries; # TypeError;ImportError;zipimport.ZipImportError; # # i.e.: true;true;true;true;true;TypeError;ImportError;zipimport.ZipImportError; # # This API is optional and works 'in bulk' -- it's possible # to get finer-grained control with CMD_ADD_EXCEPTION_BREAK/CMD_REMOVE_EXCEPTION_BREAK # which allows setting caught/uncaught per exception. splitted = text.split(';') py_db.break_on_uncaught_exceptions = {} py_db.break_on_caught_exceptions = {} if len(splitted) >= 5: if splitted[0] == 'true': break_on_uncaught = True else: break_on_uncaught = False if splitted[1] == 'true': break_on_caught = True else: break_on_caught = False if splitted[2] == 'true': py_db.skip_on_exceptions_thrown_in_same_context = True else: py_db.skip_on_exceptions_thrown_in_same_context = False if splitted[3] == 'true': py_db.ignore_exceptions_thrown_in_lines_with_ignore_exception = True else: py_db.ignore_exceptions_thrown_in_lines_with_ignore_exception = False if splitted[4] == 'true': ignore_libraries = True else: ignore_libraries = False for exception_type in splitted[5:]: exception_type = exception_type.strip() if not exception_type: continue exception_breakpoint = py_db.add_break_on_exception( exception_type, condition=None, expression=None, notify_on_handled_exceptions=break_on_caught, notify_on_unhandled_exceptions=break_on_uncaught, notify_on_first_raise_only=True, ignore_libraries=ignore_libraries, ) py_db.on_breakpoints_changed() else: sys.stderr.write("Error when setting exception list. Received: %s\n" % (text,)) elif cmd_id == CMD_GET_FILE_CONTENTS: if not IS_PY3K: # In Python 3, the frame object will have unicode for the file, whereas on python 2 it has a byte-array encoded with the filesystem encoding. text = text.encode(file_system_encoding) if os.path.exists(text): f = open(text, 'r') try: source = f.read() finally: f.close() cmd = py_db.cmd_factory.make_get_file_contents(seq, source) elif cmd_id == CMD_SET_PROPERTY_TRACE: # Command which receives whether to trace property getter/setter/deleter # text is feature_state(true/false);disable_getter/disable_setter/disable_deleter if text != "": splitted = text.split(';') if len(splitted) >= 3: if py_db.disable_property_trace is False and splitted[0] == 'true': # Replacing property by custom property only when the debugger starts pydevd_traceproperty.replace_builtin_property() py_db.disable_property_trace = True # Enable/Disable tracing of the property getter if splitted[1] == 'true': py_db.disable_property_getter_trace = True else: py_db.disable_property_getter_trace = False # Enable/Disable tracing of the property setter if splitted[2] == 'true': py_db.disable_property_setter_trace = True else: py_db.disable_property_setter_trace = False # Enable/Disable tracing of the property deleter if splitted[3] == 'true': py_db.disable_property_deleter_trace = True else: py_db.disable_property_deleter_trace = False else: # User hasn't configured any settings for property tracing pass elif cmd_id == CMD_ADD_EXCEPTION_BREAK: # Note that this message has some idiosyncrasies... # # notify_on_handled_exceptions can be 0, 1 or 2 # 0 means we should not stop on handled exceptions. # 1 means we should stop on handled exceptions showing it on all frames where the exception passes. # 2 means we should stop on handled exceptions but we should only notify about it once. # # To ignore_libraries properly, besides setting ignore_libraries to 1, the IDE_PROJECT_ROOTS environment # variable must be set (so, we'll ignore anything not below IDE_PROJECT_ROOTS) -- this is not ideal as # the environment variable may not be properly set if it didn't start from the debugger (we should # create a custom message for that). # # There are 2 global settings which can only be set in CMD_SET_PY_EXCEPTION. Namely: # # py_db.skip_on_exceptions_thrown_in_same_context # - If True, we should only show the exception in a caller, not where it was first raised. # # py_db.ignore_exceptions_thrown_in_lines_with_ignore_exception # - If True exceptions thrown in lines with '@IgnoreException' will not be shown. condition = "" expression = "" if text.find('\t') != -1: try: exception, condition, expression, notify_on_handled_exceptions, notify_on_unhandled_exceptions, ignore_libraries = text.split('\t', 5) except: exception, notify_on_handled_exceptions, notify_on_unhandled_exceptions, ignore_libraries = text.split('\t', 3) else: exception, notify_on_handled_exceptions, notify_on_unhandled_exceptions, ignore_libraries = text, 0, 0, 0 condition = condition.replace("@_@NEW_LINE_CHAR@_@", '\n').replace("@_@TAB_CHAR@_@", '\t').strip() if condition is not None and (len(condition) == 0 or condition == "None"): condition = None expression = expression.replace("@_@NEW_LINE_CHAR@_@", '\n').replace("@_@TAB_CHAR@_@", '\t').strip() if expression is not None and (len(expression) == 0 or expression == "None"): expression = None if exception.find('-') != -1: breakpoint_type, exception = exception.split('-') else: breakpoint_type = 'python' if breakpoint_type == 'python': exception_breakpoint = py_db.add_break_on_exception( exception, condition=condition, expression=expression, notify_on_handled_exceptions=int(notify_on_handled_exceptions) > 0, notify_on_unhandled_exceptions=int(notify_on_unhandled_exceptions) == 1, notify_on_first_raise_only=int(notify_on_handled_exceptions) == 2, ignore_libraries=int(ignore_libraries) > 0 ) if exception_breakpoint is not None: py_db.on_breakpoints_changed() else: supported_type = False plugin = py_db.get_plugin_lazy_init() if plugin is not None: supported_type = plugin.add_breakpoint('add_exception_breakpoint', py_db, breakpoint_type, exception) if supported_type: py_db.has_plugin_exception_breaks = py_db.plugin.has_exception_breaks() py_db.on_breakpoints_changed() else: raise NameError(breakpoint_type) elif cmd_id == CMD_REMOVE_EXCEPTION_BREAK: exception = text if exception.find('-') != -1: exception_type, exception = exception.split('-') else: exception_type = 'python' if exception_type == 'python': try: cp = py_db.break_on_uncaught_exceptions.copy() cp.pop(exception, None) py_db.break_on_uncaught_exceptions = cp cp = py_db.break_on_caught_exceptions.copy() cp.pop(exception, None) py_db.break_on_caught_exceptions = cp except: pydev_log.debug("Error while removing exception %s"%sys.exc_info()[0]) else: supported_type = False # I.e.: no need to initialize lazy (if we didn't have it in the first place, we can't remove # anything from it anyways). plugin = py_db.plugin if plugin is not None: supported_type = plugin.remove_exception_breakpoint(py_db, exception_type, exception) if supported_type: py_db.has_plugin_exception_breaks = py_db.plugin.has_exception_breaks() else: raise NameError(exception_type) py_db.on_breakpoints_changed(remove=True) elif cmd_id == CMD_LOAD_SOURCE: path = text try: if not IS_PY3K: # In Python 3, the frame object will have unicode for the file, whereas on python 2 it has a byte-array encoded with the filesystem encoding. path = path.encode(file_system_encoding) path = pydevd_file_utils.norm_file_to_server(path) f = open(path, 'r') source = f.read() cmd = py_db.cmd_factory.make_load_source_message(seq, source) except: cmd = py_db.cmd_factory.make_error_message(seq, pydevd_tracing.get_exception_traceback_str()) elif cmd_id == CMD_ADD_DJANGO_EXCEPTION_BREAK: exception = text plugin = py_db.get_plugin_lazy_init() if plugin is not None: plugin.add_breakpoint('add_exception_breakpoint', py_db, 'django', exception) py_db.has_plugin_exception_breaks = py_db.plugin.has_exception_breaks() py_db.on_breakpoints_changed() elif cmd_id == CMD_REMOVE_DJANGO_EXCEPTION_BREAK: exception = text # I.e.: no need to initialize lazy (if we didn't have it in the first place, we can't remove # anything from it anyways). plugin = py_db.plugin if plugin is not None: plugin.remove_exception_breakpoint(py_db, 'django', exception) py_db.has_plugin_exception_breaks = py_db.plugin.has_exception_breaks() py_db.on_breakpoints_changed(removed=True) elif cmd_id == CMD_EVALUATE_CONSOLE_EXPRESSION: # Command which takes care for the debug console communication if text != "": thread_id, frame_id, console_command = text.split('\t', 2) console_command, line = console_command.split('\t') if console_command == 'EVALUATE': int_cmd = InternalEvaluateConsoleExpression( seq, thread_id, frame_id, line, buffer_output=True) elif console_command == 'EVALUATE_UNBUFFERED': int_cmd = InternalEvaluateConsoleExpression( seq, thread_id, frame_id, line, buffer_output=False) elif console_command == 'GET_COMPLETIONS': int_cmd = InternalConsoleGetCompletions(seq, thread_id, frame_id, line) else: raise ValueError('Unrecognized command: %s' % (console_command,)) py_db.post_internal_command(int_cmd, thread_id) elif cmd_id == CMD_RUN_CUSTOM_OPERATION: # Command which runs a custom operation if text != "": try: location, custom = text.split('||', 1) except: sys.stderr.write('Custom operation now needs a || separator. Found: %s\n' % (text,)) raise thread_id, frame_id, scopeattrs = location.split('\t', 2) if scopeattrs.find('\t') != -1: # there are attributes beyond scope scope, attrs = scopeattrs.split('\t', 1) else: scope, attrs = (scopeattrs, None) # : style: EXECFILE or EXEC # : encoded_code_or_file: file to execute or code # : fname: name of function to be executed in the resulting namespace style, encoded_code_or_file, fnname = custom.split('\t', 3) int_cmd = InternalRunCustomOperation(seq, thread_id, frame_id, scope, attrs, style, encoded_code_or_file, fnname) py_db.post_internal_command(int_cmd, thread_id) elif cmd_id == CMD_IGNORE_THROWN_EXCEPTION_AT: if text: replace = 'REPLACE:' # Not all 3.x versions support u'REPLACE:', so, doing workaround. if not IS_PY3K: replace = unicode(replace) if text.startswith(replace): text = text[8:] py_db.filename_to_lines_where_exceptions_are_ignored.clear() if text: for line in text.split('||'): # Can be bulk-created (one in each line) filename, line_number = line.split('|') if not IS_PY3K: filename = filename.encode(file_system_encoding) filename = pydevd_file_utils.norm_file_to_server(filename) if os.path.exists(filename): lines_ignored = py_db.filename_to_lines_where_exceptions_are_ignored.get(filename) if lines_ignored is None: lines_ignored = py_db.filename_to_lines_where_exceptions_are_ignored[filename] = {} lines_ignored[int(line_number)] = 1 else: sys.stderr.write('pydev debugger: warning: trying to ignore exception thrown'\ ' on file that does not exist: %s (will have no effect)\n' % (filename,)) elif cmd_id == CMD_ENABLE_DONT_TRACE: if text: true_str = 'true' # Not all 3.x versions support u'str', so, doing workaround. if not IS_PY3K: true_str = unicode(true_str) mode = text.strip() == true_str pydevd_dont_trace.trace_filter(mode) elif cmd_id == CMD_REDIRECT_OUTPUT: if text: py_db.enable_output_redirection('STDOUT' in text, 'STDERR' in text) elif cmd_id == CMD_GET_NEXT_STATEMENT_TARGETS: thread_id, frame_id = text.split('\t', 1) int_cmd = InternalGetNextStatementTargets(seq, thread_id, frame_id) py_db.post_internal_command(int_cmd, thread_id) elif cmd_id == CMD_SET_PROJECT_ROOTS: pydevd_utils.set_project_roots(text.split(u'\t')) elif cmd_id == CMD_THREAD_DUMP_TO_STDERR: pydevd_utils.dump_threads() elif cmd_id == CMD_STOP_ON_START: py_db.stop_on_start = text.strip() in ('True', 'true', '1') elif cmd_id == CMD_PYDEVD_JSON_CONFIG: # Expected to receive a json string as: # { # 'skip_suspend_on_breakpoint_exception': [<exception names where we should suspend>], # 'skip_print_breakpoint_exception': [<exception names where we should print>], # 'multi_threads_single_notification': bool, # } msg = json.loads(text.strip()) if 'skip_suspend_on_breakpoint_exception' in msg: py_db.skip_suspend_on_breakpoint_exception = tuple( get_exception_class(x) for x in msg['skip_suspend_on_breakpoint_exception']) if 'skip_print_breakpoint_exception' in msg: py_db.skip_print_breakpoint_exception = tuple( get_exception_class(x) for x in msg['skip_print_breakpoint_exception']) if 'multi_threads_single_notification' in msg: py_db.multi_threads_single_notification = msg['multi_threads_single_notification'] elif cmd_id == CMD_GET_EXCEPTION_DETAILS: thread_id = text t = pydevd_find_thread_by_id(thread_id) frame = None if t and not getattr(t, 'pydev_do_not_trace', None): additional_info = set_additional_thread_info(t) frame = additional_info.get_topmost_frame(t) try: cmd = py_db.cmd_factory.make_get_exception_details_message(seq, thread_id, frame) finally: frame = None t = None else: #I have no idea what this is all about cmd = py_db.cmd_factory.make_error_message(seq, "unexpected command " + str(cmd_id)) if cmd is not None: py_db.writer.add_command(cmd) del cmd except Exception: traceback.print_exc() try: from StringIO import StringIO except ImportError: from io import StringIO stream = StringIO() traceback.print_exc(file=stream) cmd = py_db.cmd_factory.make_error_message( seq, "Unexpected exception in process_net_command.\nInitial params: %s. Exception: %s" % ( ((cmd_id, seq, text), stream.getvalue()) ) ) py_db.writer.add_command(cmd) finally: py_db._main_lock.release()
def getVariable(dbg, thread_id, frame_id, scope, attrs): """ returns the value of a variable :scope: can be BY_ID, EXPRESSION, GLOBAL, LOCAL, FRAME BY_ID means we'll traverse the list of all objects alive to get the object. :attrs: after reaching the proper scope, we have to get the attributes until we find the proper location (i.e.: obj\tattr1\tattr2) :note: when BY_ID is used, the frame_id is considered the id of the object to find and not the frame (as we don't care about the frame in this case). """ if scope == 'BY_ID': if thread_id != get_current_thread_id(threading.current_thread()): raise VariableError("getVariable: must execute on same thread") try: import gc objects = gc.get_objects() except: pass # Not all python variants have it. else: frame_id = int(frame_id) for var in objects: if id(var) == frame_id: if attrs is not None: attrList = attrs.split('\t') for k in attrList: _type, _type_name, resolver = get_type(var) var = resolver.resolve(var, k) return var # If it didn't return previously, we coudn't find it by id (i.e.: alrceady garbage collected). sys.stderr.write('Unable to find object with id: %s\n' % (frame_id, )) return None frame = dbg.find_frame(thread_id, frame_id) if frame is None: return {} if attrs is not None: attrList = attrs.split('\t') else: attrList = [] for attr in attrList: attr.replace("@_@TAB_CHAR@_@", '\t') if scope == 'EXPRESSION': for count in xrange(len(attrList)): if count == 0: # An Expression can be in any scope (globals/locals), therefore it needs to evaluated as an expression var = evaluate_expression(dbg, frame, attrList[count], False) else: _type, _type_name, resolver = get_type(var) var = resolver.resolve(var, attrList[count]) else: if scope == "GLOBAL": var = frame.f_globals del attrList[ 0] # globals are special, and they get a single dummy unused attribute else: # in a frame access both locals and globals as Python does var = {} var.update(frame.f_globals) var.update(frame.f_locals) for k in attrList: _type, _type_name, resolver = get_type(var) var = resolver.resolve(var, k) return var
def set_trace_in_qt(): from _pydevd_bundle.pydevd_comm import get_global_debugger debugger = get_global_debugger() if debugger is not None: threading.current_thread() # Create the dummy thread for qt. debugger.enable_tracing()
def find_frame(thread_id, frame_id): """ returns a frame on the thread that has a given frame_id """ try: curr_thread_id = get_current_thread_id(threading.current_thread()) if thread_id != curr_thread_id: try: return get_custom_frame( thread_id, frame_id ) # I.e.: thread_id could be a stackless frame id + thread_id. except: pass raise VariableError( "find_frame: must execute on same thread (%s != %s)" % (thread_id, curr_thread_id)) lookingFor = int(frame_id) if AdditionalFramesContainer.additional_frames: if thread_id in AdditionalFramesContainer.additional_frames: frame = AdditionalFramesContainer.additional_frames[ thread_id].get(lookingFor) if frame is not None: return frame curFrame = get_frame() if frame_id == "*": return curFrame # any frame is specified with "*" frameFound = None for frame in _iter_frames(curFrame): if lookingFor == id(frame): frameFound = frame del frame break del frame # Important: python can hold a reference to the frame from the current context # if an exception is raised, so, if we don't explicitly add those deletes # we might have those variables living much more than we'd want to. # I.e.: sys.exc_info holding reference to frame that raises exception (so, other places # need to call sys.exc_clear()) del curFrame if frameFound is None: msgFrames = '' i = 0 for frame in _iter_frames(get_frame()): i += 1 msgFrames += str(id(frame)) if i % 5 == 0: msgFrames += '\n' else: msgFrames += ' - ' # Note: commented this error message out (it may commonly happen # if a message asking for a frame is issued while a thread is paused # but the thread starts running before the message is actually # handled). # Leaving code to uncomment during tests. # err_msg = '''find_frame: frame not found. # Looking for thread_id:%s, frame_id:%s # Current thread_id:%s, available frames: # %s\n # ''' % (thread_id, lookingFor, curr_thread_id, msgFrames) # # sys.stderr.write(err_msg) return None return frameFound except: import traceback traceback.print_exc() return None
if int(port) == 0 and int(client_port) == 0: (h, p) = pydev_localhost.get_socket_name() client_port = p host = pydev_localhost.get_localhost() #replace exit (see comments on method) #note that this does not work in jython!!! (sys method can't be replaced). sys.exit = skip_successful_exit connect_status_queue = _queue.Queue() interpreter = InterpreterInterface( host, int(client_port), threading.current_thread(), connect_status_queue=connect_status_queue) server_thread = threading.Thread(target=start_console_server, name='ServerThread', args=(host, int(port), interpreter)) server_thread.daemon = True server_thread.start() sys.stdin = StdIn(interpreter, host, client_port, sys.stdin) init_mpl_in_console(interpreter) try: success = connect_status_queue.get(True, 60) if not success:
def process_net_command(py_db, cmd_id, seq, text): '''Processes a command received from the Java side @param cmd_id: the id of the command @param seq: the sequence of the command @param text: the text received in the command @note: this method is run as a big switch... after doing some tests, it's not clear whether changing it for a dict id --> function call will have better performance result. A simple test with xrange(10000000) showed that the gains from having a fast access to what should be executed are lost because of the function call in a way that if we had 10 elements in the switch the if..elif are better -- but growing the number of choices makes the solution with the dispatch look better -- so, if this gets more than 20-25 choices at some time, it may be worth refactoring it (actually, reordering the ifs so that the ones used mostly come before probably will give better performance). ''' # print(ID_TO_MEANING[str(cmd_id)], repr(text)) py_db._main_lock.acquire() try: try: cmd = None if cmd_id == CMD_RUN: py_db.ready_to_run = True elif cmd_id == CMD_SET_PROTOCOL: expected = (NetCommand.HTTP_PROTOCOL, NetCommand.QUOTED_LINE_PROTOCOL) text = text.strip() assert text.strip( ) in expected, 'Protocol (%s) should be one of: %s' % ( text, expected) NetCommand.protocol = text cmd = py_db.cmd_factory.make_protocol_set_message(seq) elif cmd_id == CMD_VERSION: # response is version number # ide_os should be 'WINDOWS' or 'UNIX'. # Default based on server process (although ideally the IDE should # provide it). if IS_WINDOWS: ide_os = 'WINDOWS' else: ide_os = 'UNIX' # Breakpoints can be grouped by 'LINE' or by 'ID'. breakpoints_by = 'LINE' splitted = text.split('\t') if len(splitted) == 1: _local_version = splitted elif len(splitted) == 2: _local_version, ide_os = splitted elif len(splitted) == 3: _local_version, ide_os, breakpoints_by = splitted if breakpoints_by == 'ID': py_db._set_breakpoints_with_id = True else: py_db._set_breakpoints_with_id = False pydevd_file_utils.set_ide_os(ide_os) cmd = py_db.cmd_factory.make_version_message(seq) elif cmd_id == CMD_LIST_THREADS: # response is a list of threads cmd = py_db.cmd_factory.make_list_threads_message(seq) elif cmd_id == CMD_GET_THREAD_STACK: # Receives a thread_id and a given timeout, which is the time we should # wait to the provide the stack if a given thread is still not suspended. if '\t' in text: thread_id, timeout = text.split('\t') timeout = float(timeout) else: thread_id = text timeout = .5 # Default timeout is .5 seconds # If it's already suspended, get it right away. internal_get_thread_stack = InternalGetThreadStack( seq, thread_id, py_db, timeout=timeout) if internal_get_thread_stack.can_be_executed_by( get_thread_id(threading.current_thread())): internal_get_thread_stack.do_it(py_db) else: py_db.post_internal_command(internal_get_thread_stack, '*') elif cmd_id == CMD_THREAD_SUSPEND: # Yes, thread suspend is done at this point, not through an internal command. threads = [] suspend_all = text.strip() == '*' if suspend_all: threads = pydevd_utils.get_non_pydevd_threads() elif text.startswith('__frame__:'): sys.stderr.write("Can't suspend tasklet: %s\n" % (text, )) else: threads = [pydevd_find_thread_by_id(text)] for t in threads: py_db.set_suspend( t, CMD_THREAD_SUSPEND, suspend_other_threads=suspend_all, is_pause=True, ) # Break here (even if it's suspend all) as py_db.set_suspend will # take care of suspending other threads. break elif cmd_id == CMD_THREAD_RUN: threads = [] if text.strip() == '*': threads = pydevd_utils.get_non_pydevd_threads() elif text.startswith('__frame__:'): sys.stderr.write("Can't make tasklet run: %s\n" % (text, )) else: threads = [pydevd_find_thread_by_id(text)] for t in threads: additional_info = set_additional_thread_info(t) additional_info.pydev_step_cmd = -1 additional_info.pydev_step_stop = None additional_info.pydev_state = STATE_RUN elif cmd_id == CMD_STEP_INTO or cmd_id == CMD_STEP_OVER or cmd_id == CMD_STEP_RETURN or \ cmd_id == CMD_STEP_INTO_MY_CODE: # we received some command to make a single step t = pydevd_find_thread_by_id(text) if t: thread_id = get_thread_id(t) int_cmd = InternalStepThread(thread_id, cmd_id) py_db.post_internal_command(int_cmd, thread_id) elif text.startswith('__frame__:'): sys.stderr.write("Can't make tasklet step command: %s\n" % (text, )) elif cmd_id == CMD_RUN_TO_LINE or cmd_id == CMD_SET_NEXT_STATEMENT or cmd_id == CMD_SMART_STEP_INTO: # we received some command to make a single step thread_id, line, func_name = text.split('\t', 2) t = pydevd_find_thread_by_id(thread_id) if t: int_cmd = InternalSetNextStatementThread( thread_id, cmd_id, line, func_name) py_db.post_internal_command(int_cmd, thread_id) elif thread_id.startswith('__frame__:'): sys.stderr.write( "Can't set next statement in tasklet: %s\n" % (thread_id, )) elif cmd_id == CMD_RELOAD_CODE: # we received some command to make a reload of a module module_name = text.strip() thread_id = '*' # Any thread # Note: not going for the main thread because in this case it'd only do the load # when we stopped on a breakpoint. int_cmd = ReloadCodeCommand(module_name, thread_id) py_db.post_internal_command(int_cmd, thread_id) elif cmd_id == CMD_CHANGE_VARIABLE: # the text is: thread\tstackframe\tFRAME|GLOBAL\tattribute_to_change\tvalue_to_change try: thread_id, frame_id, scope, attr_and_value = text.split( '\t', 3) tab_index = attr_and_value.rindex('\t') attr = attr_and_value[0:tab_index].replace('\t', '.') value = attr_and_value[tab_index + 1:] int_cmd = InternalChangeVariable(seq, thread_id, frame_id, scope, attr, value) py_db.post_internal_command(int_cmd, thread_id) except: traceback.print_exc() elif cmd_id == CMD_GET_VARIABLE: # we received some command to get a variable # the text is: thread_id\tframe_id\tFRAME|GLOBAL\tattributes* try: thread_id, frame_id, scopeattrs = text.split('\t', 2) if scopeattrs.find( '\t') != -1: # there are attributes beyond scope scope, attrs = scopeattrs.split('\t', 1) else: scope, attrs = (scopeattrs, None) int_cmd = InternalGetVariable(seq, thread_id, frame_id, scope, attrs) py_db.post_internal_command(int_cmd, thread_id) except: traceback.print_exc() elif cmd_id == CMD_GET_ARRAY: # we received some command to get an array variable # the text is: thread_id\tframe_id\tFRAME|GLOBAL\tname\ttemp\troffs\tcoffs\trows\tcols\tformat try: roffset, coffset, rows, cols, format, thread_id, frame_id, scopeattrs = text.split( '\t', 7) if scopeattrs.find( '\t') != -1: # there are attributes beyond scope scope, attrs = scopeattrs.split('\t', 1) else: scope, attrs = (scopeattrs, None) int_cmd = InternalGetArray(seq, roffset, coffset, rows, cols, format, thread_id, frame_id, scope, attrs) py_db.post_internal_command(int_cmd, thread_id) except: traceback.print_exc() elif cmd_id == CMD_SHOW_RETURN_VALUES: try: show_return_values = text.split('\t')[1] if int(show_return_values) == 1: py_db.show_return_values = True else: if py_db.show_return_values: # We should remove saved return values py_db.remove_return_values_flag = True py_db.show_return_values = False pydev_log.debug("Show return values: %s\n" % py_db.show_return_values) except: traceback.print_exc() elif cmd_id == CMD_LOAD_FULL_VALUE: try: thread_id, frame_id, scopeattrs = text.split('\t', 2) vars = scopeattrs.split(NEXT_VALUE_SEPARATOR) int_cmd = InternalLoadFullValue(seq, thread_id, frame_id, vars) py_db.post_internal_command(int_cmd, thread_id) except: traceback.print_exc() elif cmd_id == CMD_GET_COMPLETIONS: # we received some command to get a variable # the text is: thread_id\tframe_id\tactivation token try: thread_id, frame_id, scope, act_tok = text.split('\t', 3) int_cmd = InternalGetCompletions(seq, thread_id, frame_id, act_tok) py_db.post_internal_command(int_cmd, thread_id) except: traceback.print_exc() elif cmd_id == CMD_GET_DESCRIPTION: try: thread_id, frame_id, expression = text.split('\t', 2) int_cmd = InternalGetDescription(seq, thread_id, frame_id, expression) py_db.post_internal_command(int_cmd, thread_id) except: traceback.print_exc() elif cmd_id == CMD_GET_FRAME: thread_id, frame_id, scope = text.split('\t', 2) int_cmd = InternalGetFrame(seq, thread_id, frame_id) py_db.post_internal_command(int_cmd, thread_id) elif cmd_id == CMD_SET_BREAK: # func name: 'None': match anything. Empty: match global, specified: only method context. # command to add some breakpoint. # text is file\tline. Add to breakpoints dictionary suspend_policy = "NONE" # Can be 'NONE' or 'ALL' is_logpoint = False hit_condition = None if py_db._set_breakpoints_with_id: try: try: breakpoint_id, type, file, line, func_name, condition, expression, hit_condition, is_logpoint, suspend_policy = text.split( '\t', 9) except ValueError: # not enough values to unpack # No suspend_policy passed (use default). breakpoint_id, type, file, line, func_name, condition, expression, hit_condition, is_logpoint = text.split( '\t', 8) is_logpoint = is_logpoint == 'True' except ValueError: # not enough values to unpack breakpoint_id, type, file, line, func_name, condition, expression = text.split( '\t', 6) breakpoint_id = int(breakpoint_id) line = int(line) # We must restore new lines and tabs as done in # AbstractDebugTarget.breakpointAdded condition = condition.replace("@_@NEW_LINE_CHAR@_@", '\n').\ replace("@_@TAB_CHAR@_@", '\t').strip() expression = expression.replace("@_@NEW_LINE_CHAR@_@", '\n').\ replace("@_@TAB_CHAR@_@", '\t').strip() else: # Note: this else should be removed after PyCharm migrates to setting # breakpoints by id (and ideally also provides func_name). type, file, line, func_name, suspend_policy, condition, expression = text.split( '\t', 6) # If we don't have an id given for each breakpoint, consider # the id to be the line. breakpoint_id = line = int(line) condition = condition.replace("@_@NEW_LINE_CHAR@_@", '\n'). \ replace("@_@TAB_CHAR@_@", '\t').strip() expression = expression.replace("@_@NEW_LINE_CHAR@_@", '\n'). \ replace("@_@TAB_CHAR@_@", '\t').strip() if not IS_PY3K: # In Python 3, the frame object will have unicode for the file, whereas on python 2 it has a byte-array encoded with the filesystem encoding. file = file.encode(file_system_encoding) file = pydevd_file_utils.norm_file_to_server(file) if not pydevd_file_utils.exists(file): sys.stderr.write('pydev debugger: warning: trying to add breakpoint'\ ' to file that does not exist: %s (will have no effect)\n' % (file,)) sys.stderr.flush() if condition is not None and (len(condition) <= 0 or condition == "None"): condition = None if expression is not None and (len(expression) <= 0 or expression == "None"): expression = None if hit_condition is not None and (len(hit_condition) <= 0 or hit_condition == "None"): hit_condition = None if type == 'python-line': breakpoint = LineBreakpoint(line, condition, func_name, expression, suspend_policy, hit_condition=hit_condition, is_logpoint=is_logpoint) breakpoints = py_db.breakpoints file_to_id_to_breakpoint = py_db.file_to_id_to_line_breakpoint supported_type = True else: result = None plugin = py_db.get_plugin_lazy_init() if plugin is not None: result = plugin.add_breakpoint( 'add_line_breakpoint', py_db, type, file, line, condition, expression, func_name, hit_condition=hit_condition, is_logpoint=is_logpoint) if result is not None: supported_type = True breakpoint, breakpoints = result file_to_id_to_breakpoint = py_db.file_to_id_to_plugin_breakpoint else: supported_type = False if not supported_type: raise NameError(type) if DebugInfoHolder.DEBUG_TRACE_BREAKPOINTS > 0: pydev_log.debug( 'Added breakpoint:%s - line:%s - func_name:%s\n' % (file, line, func_name.encode('utf-8'))) sys.stderr.flush() if file in file_to_id_to_breakpoint: id_to_pybreakpoint = file_to_id_to_breakpoint[file] else: id_to_pybreakpoint = file_to_id_to_breakpoint[file] = {} id_to_pybreakpoint[breakpoint_id] = breakpoint py_db.consolidate_breakpoints(file, id_to_pybreakpoint, breakpoints) if py_db.plugin is not None: py_db.has_plugin_line_breaks = py_db.plugin.has_line_breaks( ) py_db.set_tracing_for_untraced_contexts_if_not_frame_eval() py_db.enable_tracing_in_frames_while_running_if_frame_eval() elif cmd_id == CMD_REMOVE_BREAK: #command to remove some breakpoint #text is type\file\tid. Remove from breakpoints dictionary breakpoint_type, file, breakpoint_id = text.split('\t', 2) if not IS_PY3K: # In Python 3, the frame object will have unicode for the file, whereas on python 2 it has a byte-array encoded with the filesystem encoding. file = file.encode(file_system_encoding) file = pydevd_file_utils.norm_file_to_server(file) try: breakpoint_id = int(breakpoint_id) except ValueError: pydev_log.error( 'Error removing breakpoint. Expected breakpoint_id to be an int. Found: %s' % (breakpoint_id, )) else: file_to_id_to_breakpoint = None if breakpoint_type == 'python-line': breakpoints = py_db.breakpoints file_to_id_to_breakpoint = py_db.file_to_id_to_line_breakpoint elif py_db.get_plugin_lazy_init() is not None: result = py_db.plugin.get_breakpoints( py_db, breakpoint_type) if result is not None: file_to_id_to_breakpoint = py_db.file_to_id_to_plugin_breakpoint breakpoints = result if file_to_id_to_breakpoint is None: pydev_log.error( 'Error removing breakpoint. Cant handle breakpoint of type %s' % breakpoint_type) else: try: id_to_pybreakpoint = file_to_id_to_breakpoint.get( file, {}) if DebugInfoHolder.DEBUG_TRACE_BREAKPOINTS > 0: existing = id_to_pybreakpoint[breakpoint_id] sys.stderr.write( 'Removed breakpoint:%s - line:%s - func_name:%s (id: %s)\n' % (file, existing.line, existing.func_name.encode('utf-8'), breakpoint_id)) del id_to_pybreakpoint[breakpoint_id] py_db.consolidate_breakpoints( file, id_to_pybreakpoint, breakpoints) if py_db.plugin is not None: py_db.has_plugin_line_breaks = py_db.plugin.has_line_breaks( ) except KeyError: pydev_log.error( "Error removing breakpoint: Breakpoint id not found: %s id: %s. Available ids: %s\n" % (file, breakpoint_id, dict_keys(id_to_pybreakpoint))) elif cmd_id == CMD_EVALUATE_EXPRESSION or cmd_id == CMD_EXEC_EXPRESSION: #command to evaluate the given expression #text is: thread\tstackframe\tLOCAL\texpression temp_name = "" try: thread_id, frame_id, scope, expression, trim, temp_name = text.split( '\t', 5) except ValueError: thread_id, frame_id, scope, expression, trim = text.split( '\t', 4) int_cmd = InternalEvaluateExpression( seq, thread_id, frame_id, expression, cmd_id == CMD_EXEC_EXPRESSION, int(trim) == 1, temp_name) py_db.post_internal_command(int_cmd, thread_id) elif cmd_id == CMD_CONSOLE_EXEC: #command to exec expression in console, in case expression is only partially valid 'False' is returned #text is: thread\tstackframe\tLOCAL\texpression thread_id, frame_id, scope, expression = text.split('\t', 3) int_cmd = InternalConsoleExec(seq, thread_id, frame_id, expression) py_db.post_internal_command(int_cmd, thread_id) elif cmd_id == CMD_SET_PY_EXCEPTION: # Command which receives set of exceptions on which user wants to break the debugger # text is: # # break_on_uncaught; # break_on_caught; # skip_on_exceptions_thrown_in_same_context; # ignore_exceptions_thrown_in_lines_with_ignore_exception; # ignore_libraries; # TypeError;ImportError;zipimport.ZipImportError; # # i.e.: true;true;true;true;true;TypeError;ImportError;zipimport.ZipImportError; # # This API is optional and works 'in bulk' -- it's possible # to get finer-grained control with CMD_ADD_EXCEPTION_BREAK/CMD_REMOVE_EXCEPTION_BREAK # which allows setting caught/uncaught per exception. splitted = text.split(';') py_db.break_on_uncaught_exceptions = {} py_db.break_on_caught_exceptions = {} added = [] if len(splitted) >= 5: if splitted[0] == 'true': break_on_uncaught = True else: break_on_uncaught = False if splitted[1] == 'true': break_on_caught = True else: break_on_caught = False if splitted[2] == 'true': py_db.skip_on_exceptions_thrown_in_same_context = True else: py_db.skip_on_exceptions_thrown_in_same_context = False if splitted[3] == 'true': py_db.ignore_exceptions_thrown_in_lines_with_ignore_exception = True else: py_db.ignore_exceptions_thrown_in_lines_with_ignore_exception = False if splitted[4] == 'true': ignore_libraries = True else: ignore_libraries = False for exception_type in splitted[5:]: exception_type = exception_type.strip() if not exception_type: continue exception_breakpoint = py_db.add_break_on_exception( exception_type, condition=None, expression=None, notify_on_handled_exceptions=break_on_caught, notify_on_unhandled_exceptions=break_on_uncaught, notify_on_first_raise_only=True, ignore_libraries=ignore_libraries, ) if exception_breakpoint is None: continue added.append(exception_breakpoint) py_db.enable_tracing_in_frames_while_running_if_frame_eval( ) py_db.set_tracing_for_untraced_contexts_if_not_frame_eval() else: sys.stderr.write( "Error when setting exception list. Received: %s\n" % (text, )) elif cmd_id == CMD_GET_FILE_CONTENTS: if not IS_PY3K: # In Python 3, the frame object will have unicode for the file, whereas on python 2 it has a byte-array encoded with the filesystem encoding. text = text.encode(file_system_encoding) if os.path.exists(text): f = open(text, 'r') try: source = f.read() finally: f.close() cmd = py_db.cmd_factory.make_get_file_contents(seq, source) elif cmd_id == CMD_SET_PROPERTY_TRACE: # Command which receives whether to trace property getter/setter/deleter # text is feature_state(true/false);disable_getter/disable_setter/disable_deleter if text != "": splitted = text.split(';') if len(splitted) >= 3: if py_db.disable_property_trace is False and splitted[ 0] == 'true': # Replacing property by custom property only when the debugger starts pydevd_traceproperty.replace_builtin_property() py_db.disable_property_trace = True # Enable/Disable tracing of the property getter if splitted[1] == 'true': py_db.disable_property_getter_trace = True else: py_db.disable_property_getter_trace = False # Enable/Disable tracing of the property setter if splitted[2] == 'true': py_db.disable_property_setter_trace = True else: py_db.disable_property_setter_trace = False # Enable/Disable tracing of the property deleter if splitted[3] == 'true': py_db.disable_property_deleter_trace = True else: py_db.disable_property_deleter_trace = False else: # User hasn't configured any settings for property tracing pass elif cmd_id == CMD_ADD_EXCEPTION_BREAK: # Note that this message has some idiosyncrasies... # # notify_on_handled_exceptions can be 0, 1 or 2 # 0 means we should not stop on handled exceptions. # 1 means we should stop on handled exceptions showing it on all frames where the exception passes. # 2 means we should stop on handled exceptions but we should only notify about it once. # # To ignore_libraries properly, besides setting ignore_libraries to 1, the IDE_PROJECT_ROOTS environment # variable must be set (so, we'll ignore anything not below IDE_PROJECT_ROOTS) -- this is not ideal as # the environment variable may not be properly set if it didn't start from the debugger (we should # create a custom message for that). # # There are 2 global settings which can only be set in CMD_SET_PY_EXCEPTION. Namely: # # py_db.skip_on_exceptions_thrown_in_same_context # - If True, we should only show the exception in a caller, not where it was first raised. # # py_db.ignore_exceptions_thrown_in_lines_with_ignore_exception # - If True exceptions thrown in lines with '@IgnoreException' will not be shown. condition = "" expression = "" if text.find('\t') != -1: try: exception, condition, expression, notify_on_handled_exceptions, notify_on_unhandled_exceptions, ignore_libraries = text.split( '\t', 5) except: exception, notify_on_handled_exceptions, notify_on_unhandled_exceptions, ignore_libraries = text.split( '\t', 3) else: exception, notify_on_handled_exceptions, notify_on_unhandled_exceptions, ignore_libraries = text, 0, 0, 0 condition = condition.replace("@_@NEW_LINE_CHAR@_@", '\n').replace( "@_@TAB_CHAR@_@", '\t').strip() if condition is not None and (len(condition) == 0 or condition == "None"): condition = None expression = expression.replace("@_@NEW_LINE_CHAR@_@", '\n').replace( "@_@TAB_CHAR@_@", '\t').strip() if expression is not None and (len(expression) == 0 or expression == "None"): expression = None if exception.find('-') != -1: breakpoint_type, exception = exception.split('-') else: breakpoint_type = 'python' if breakpoint_type == 'python': exception_breakpoint = py_db.add_break_on_exception( exception, condition=condition, expression=expression, notify_on_handled_exceptions=int( notify_on_handled_exceptions) > 0, notify_on_unhandled_exceptions=int( notify_on_unhandled_exceptions) == 1, notify_on_first_raise_only=int( notify_on_handled_exceptions) == 2, ignore_libraries=int(ignore_libraries) > 0) if exception_breakpoint is not None: py_db.enable_tracing_in_frames_while_running_if_frame_eval( ) py_db.set_tracing_for_untraced_contexts_if_not_frame_eval( ) else: supported_type = False plugin = py_db.get_plugin_lazy_init() if plugin is not None: supported_type = plugin.add_breakpoint( 'add_exception_breakpoint', py_db, breakpoint_type, exception) if supported_type: py_db.has_plugin_exception_breaks = py_db.plugin.has_exception_breaks( ) py_db.enable_tracing_in_frames_while_running_if_frame_eval( ) else: raise NameError(breakpoint_type) elif cmd_id == CMD_REMOVE_EXCEPTION_BREAK: exception = text if exception.find('-') != -1: exception_type, exception = exception.split('-') else: exception_type = 'python' if exception_type == 'python': try: cp = py_db.break_on_uncaught_exceptions.copy() cp.pop(exception, None) py_db.break_on_uncaught_exceptions = cp cp = py_db.break_on_caught_exceptions.copy() cp.pop(exception, None) py_db.break_on_caught_exceptions = cp except: pydev_log.debug("Error while removing exception %s" % sys.exc_info()[0]) py_db.set_tracing_for_untraced_contexts_if_not_frame_eval() else: supported_type = False # I.e.: no need to initialize lazy (if we didn't have it in the first place, we can't remove # anything from it anyways). plugin = py_db.plugin if plugin is not None: supported_type = plugin.remove_exception_breakpoint( py_db, exception_type, exception) if supported_type: py_db.has_plugin_exception_breaks = py_db.plugin.has_exception_breaks( ) else: raise NameError(exception_type) if len(py_db.break_on_caught_exceptions ) == 0 and not py_db.has_plugin_exception_breaks: py_db.disable_tracing_while_running_if_frame_eval() elif cmd_id == CMD_LOAD_SOURCE: path = text try: if not IS_PY3K: # In Python 3, the frame object will have unicode for the file, whereas on python 2 it has a byte-array encoded with the filesystem encoding. path = path.encode(file_system_encoding) path = pydevd_file_utils.norm_file_to_server(path) f = open(path, 'r') source = f.read() cmd = py_db.cmd_factory.make_load_source_message( seq, source) except: cmd = py_db.cmd_factory.make_error_message( seq, pydevd_tracing.get_exception_traceback_str()) elif cmd_id == CMD_ADD_DJANGO_EXCEPTION_BREAK: exception = text plugin = py_db.get_plugin_lazy_init() if plugin is not None: plugin.add_breakpoint('add_exception_breakpoint', py_db, 'django', exception) py_db.has_plugin_exception_breaks = py_db.plugin.has_exception_breaks( ) py_db.enable_tracing_in_frames_while_running_if_frame_eval( ) elif cmd_id == CMD_REMOVE_DJANGO_EXCEPTION_BREAK: exception = text # I.e.: no need to initialize lazy (if we didn't have it in the first place, we can't remove # anything from it anyways). plugin = py_db.plugin if plugin is not None: plugin.remove_exception_breakpoint(py_db, 'django', exception) py_db.has_plugin_exception_breaks = py_db.plugin.has_exception_breaks( ) if len(py_db.break_on_caught_exceptions ) == 0 and not py_db.has_plugin_exception_breaks: py_db.disable_tracing_while_running_if_frame_eval() elif cmd_id == CMD_EVALUATE_CONSOLE_EXPRESSION: # Command which takes care for the debug console communication if text != "": thread_id, frame_id, console_command = text.split('\t', 2) console_command, line = console_command.split('\t') if console_command == 'EVALUATE': int_cmd = InternalEvaluateConsoleExpression( seq, thread_id, frame_id, line, buffer_output=True) elif console_command == 'EVALUATE_UNBUFFERED': int_cmd = InternalEvaluateConsoleExpression( seq, thread_id, frame_id, line, buffer_output=False) elif console_command == 'GET_COMPLETIONS': int_cmd = InternalConsoleGetCompletions( seq, thread_id, frame_id, line) else: raise ValueError('Unrecognized command: %s' % (console_command, )) py_db.post_internal_command(int_cmd, thread_id) elif cmd_id == CMD_RUN_CUSTOM_OPERATION: # Command which runs a custom operation if text != "": try: location, custom = text.split('||', 1) except: sys.stderr.write( 'Custom operation now needs a || separator. Found: %s\n' % (text, )) raise thread_id, frame_id, scopeattrs = location.split('\t', 2) if scopeattrs.find( '\t') != -1: # there are attributes beyond scope scope, attrs = scopeattrs.split('\t', 1) else: scope, attrs = (scopeattrs, None) # : style: EXECFILE or EXEC # : encoded_code_or_file: file to execute or code # : fname: name of function to be executed in the resulting namespace style, encoded_code_or_file, fnname = custom.split('\t', 3) int_cmd = InternalRunCustomOperation( seq, thread_id, frame_id, scope, attrs, style, encoded_code_or_file, fnname) py_db.post_internal_command(int_cmd, thread_id) elif cmd_id == CMD_IGNORE_THROWN_EXCEPTION_AT: if text: replace = 'REPLACE:' # Not all 3.x versions support u'REPLACE:', so, doing workaround. if not IS_PY3K: replace = unicode(replace) if text.startswith(replace): text = text[8:] py_db.filename_to_lines_where_exceptions_are_ignored.clear( ) if text: for line in text.split( '||' ): # Can be bulk-created (one in each line) filename, line_number = line.split('|') if not IS_PY3K: filename = filename.encode( file_system_encoding) filename = pydevd_file_utils.norm_file_to_server( filename) if os.path.exists(filename): lines_ignored = py_db.filename_to_lines_where_exceptions_are_ignored.get( filename) if lines_ignored is None: lines_ignored = py_db.filename_to_lines_where_exceptions_are_ignored[ filename] = {} lines_ignored[int(line_number)] = 1 else: sys.stderr.write('pydev debugger: warning: trying to ignore exception thrown'\ ' on file that does not exist: %s (will have no effect)\n' % (filename,)) elif cmd_id == CMD_ENABLE_DONT_TRACE: if text: true_str = 'true' # Not all 3.x versions support u'str', so, doing workaround. if not IS_PY3K: true_str = unicode(true_str) mode = text.strip() == true_str pydevd_dont_trace.trace_filter(mode) elif cmd_id == CMD_REDIRECT_OUTPUT: if text: py_db.enable_output_redirection('STDOUT' in text, 'STDERR' in text) elif cmd_id == CMD_GET_NEXT_STATEMENT_TARGETS: thread_id, frame_id = text.split('\t', 1) int_cmd = InternalGetNextStatementTargets( seq, thread_id, frame_id) py_db.post_internal_command(int_cmd, thread_id) elif cmd_id == CMD_SET_PROJECT_ROOTS: pydevd_utils.set_project_roots(text.split(u'\t')) elif cmd_id == CMD_THREAD_DUMP_TO_STDERR: pydevd_utils.dump_threads() elif cmd_id == CMD_STOP_ON_START: py_db.stop_on_start = text.strip() in ('True', 'true', '1') elif cmd_id == CMD_PYDEVD_JSON_CONFIG: # Expected to receive a json string as: # { # 'skip_suspend_on_breakpoint_exception': [<exception names where we should suspend>], # 'skip_print_breakpoint_exception': [<exception names where we should print>], # 'multi_threads_single_notification': bool, # } msg = json.loads(text.strip()) if 'skip_suspend_on_breakpoint_exception' in msg: py_db.skip_suspend_on_breakpoint_exception = tuple( get_exception_class(x) for x in msg['skip_suspend_on_breakpoint_exception']) if 'skip_print_breakpoint_exception' in msg: py_db.skip_print_breakpoint_exception = tuple( get_exception_class(x) for x in msg['skip_print_breakpoint_exception']) if 'multi_threads_single_notification' in msg: py_db.multi_threads_single_notification = msg[ 'multi_threads_single_notification'] elif cmd_id == CMD_GET_EXCEPTION_DETAILS: thread_id = text t = pydevd_find_thread_by_id(thread_id) frame = None if t and not getattr(t, 'pydev_do_not_trace', None): additional_info = set_additional_thread_info(t) frame = additional_info.get_topmost_frame(t) try: cmd = py_db.cmd_factory.make_get_exception_details_message( seq, thread_id, frame) finally: frame = None t = None else: #I have no idea what this is all about cmd = py_db.cmd_factory.make_error_message( seq, "unexpected command " + str(cmd_id)) if cmd is not None: py_db.writer.add_command(cmd) del cmd except Exception: traceback.print_exc() try: from StringIO import StringIO except ImportError: from io import StringIO stream = StringIO() traceback.print_exc(file=stream) cmd = py_db.cmd_factory.make_error_message( seq, "Unexpected exception in process_net_command.\nInitial params: %s. Exception: %s" % (((cmd_id, seq, text), stream.getvalue()))) py_db.writer.add_command(cmd) finally: py_db._main_lock.release()
def is_current_thread_main_thread(): if hasattr(threading, 'main_thread'): return threading.current_thread() is threading.main_thread() else: return isinstance(threading.current_thread(), threading._MainThread)