def make_get_thread_stack_message(self, py_db, seq, thread_id, topmost_frame, must_be_suspended=False): """ Returns thread stack as XML. :param be_suspended: If True and the thread is not suspended, returns None. """ try: # If frame is None, the return is an empty frame list. cmd_text = ['<xml><thread id="%s">' % (thread_id,)] if topmost_frame is not None: frame_id_to_lineno = {} try: # : :type suspended_frames_manager: SuspendedFramesManager suspended_frames_manager = py_db.suspended_frames_manager info = suspended_frames_manager.get_topmost_frame_and_frame_id_to_line(thread_id) if info is None: # Could not find stack of suspended frame... if must_be_suspended: return None else: # Note: we have to use the topmost frame where it was suspended (it may # be different if it was an exception). topmost_frame, frame_id_to_lineno = info cmd_text.append(self.make_thread_stack_str(topmost_frame, frame_id_to_lineno)) finally: topmost_frame = None cmd_text.append('</thread></xml>') return NetCommand(CMD_GET_THREAD_STACK, seq, ''.join(cmd_text)) except: return self.make_error_message(seq, get_exception_traceback_str())
def do_it(self, dbg): ''' Converts request into python variable ''' try: xml = StringIO.StringIO() xml.write("<xml>") _typeName, val_dict = pydevd_vars.resolve_compound_variable_fields(dbg, self.thread_id, self.frame_id, self.scope, self.attributes) if val_dict is None: val_dict = {} # assume properly ordered if resolver returns 'OrderedDict' # check type as string to support OrderedDict backport for older Python keys = dict_keys(val_dict) if not (_typeName == "OrderedDict" or val_dict.__class__.__name__ == "OrderedDict" or IS_PY36_OR_GREATER): keys.sort(key=compare_object_attrs_key) for k in keys: val = val_dict[k] evaluate_full_value = pydevd_xml.should_evaluate_full_value(val) xml.write(pydevd_xml.var_to_xml(val, k, evaluate_full_value=evaluate_full_value)) xml.write("</xml>") cmd = dbg.cmd_factory.make_get_variable_message(self.sequence, xml.getvalue()) xml.close() dbg.writer.add_command(cmd) except Exception: cmd = dbg.cmd_factory.make_error_message( self.sequence, "Error resolving variables %s" % (get_exception_traceback_str(),)) dbg.writer.add_command(cmd)
def make_get_exception_details_message(self, seq, thread_id, topmost_frame): """Returns exception details as XML """ try: # If the debugger is not suspended, just return the thread and its id. cmd_text = ['<xml><thread id="%s" ' % (thread_id,)] if topmost_frame is not None: try: frame = topmost_frame topmost_frame = None while frame is not None: if frame.f_code.co_name == 'do_wait_suspend' and frame.f_code.co_filename.endswith('pydevd.py'): arg = frame.f_locals.get('arg', None) if arg is not None: exc_type, exc_desc, _thread_suspend_str, thread_stack_str = self._make_send_curr_exception_trace_str( thread_id, *arg) cmd_text.append('exc_type="%s" ' % (exc_type,)) cmd_text.append('exc_desc="%s" ' % (exc_desc,)) cmd_text.append('>') cmd_text.append(thread_stack_str) break frame = frame.f_back else: cmd_text.append('>') finally: frame = None cmd_text.append('</thread></xml>') return NetCommand(CMD_GET_EXCEPTION_DETAILS, seq, ''.join(cmd_text)) except: return self.make_error_message(seq, get_exception_traceback_str())
def do_it(self, dbg): ''' Create an XML for console output, error and more (true/false) <xml> <output message=output_message></output> <error message=error_message></error> <more>true/false</more> </xml> ''' try: frame = dbg.find_frame(self.thread_id, self.frame_id) if frame is not None: console_message = pydevd_console.execute_console_command( frame, self.thread_id, self.frame_id, self.line, self.buffer_output) cmd = dbg.cmd_factory.make_send_console_message(self.sequence, console_message.to_xml()) else: from _pydevd_bundle.pydevd_console import ConsoleMessage console_message = ConsoleMessage() console_message.add_console_message( pydevd_console.CONSOLE_ERROR, "Select the valid frame in the debug view (thread: %s, frame: %s invalid)" % (self.thread_id, self.frame_id), ) cmd = dbg.cmd_factory.make_error_message(self.sequence, console_message.to_xml()) except: exc = get_exception_traceback_str() cmd = dbg.cmd_factory.make_error_message(self.sequence, "Error evaluating expression " + exc) dbg.writer.add_command(cmd)
def make_send_curr_exception_trace_message(self, seq, thread_id, curr_frame_id, exc_type, exc_desc, trace_obj): try: exc_type, exc_desc, thread_suspend_str, _thread_stack_str = self._make_send_curr_exception_trace_str( thread_id, exc_type, exc_desc, trace_obj) payload = str(curr_frame_id) + '\t' + exc_type + "\t" + exc_desc + "\t" + thread_suspend_str return NetCommand(CMD_SEND_CURR_EXCEPTION_TRACE, seq, payload) except Exception: return self.make_error_message(seq, get_exception_traceback_str())
def make_exit_message(self): try: net = NetCommand(CMD_EXIT, 0, '') except: net = self.make_error_message(0, get_exception_traceback_str()) return net
def do_it(self, dbg): try: cmd = dbg.cmd_factory.make_send_curr_exception_trace_proceeded_message(self.sequence, self.thread_id) dbg.writer.add_command(cmd) except: exc = get_exception_traceback_str() sys.stderr.write('%s\n' % (exc,)) cmd = dbg.cmd_factory.make_error_message(self.sequence, "Error Sending Current Exception Trace Proceeded: " + exc) dbg.writer.add_command(cmd)
def make_thread_suspend_message(self, thread_id, frame, stop_reason, message, suspend_type, frame_id_to_lineno=None): try: thread_suspend_str, thread_stack_str = self.make_thread_suspend_str( thread_id, frame, stop_reason, message, suspend_type, frame_id_to_lineno=frame_id_to_lineno) cmd = NetCommand(CMD_THREAD_SUSPEND, 0, thread_suspend_str) cmd.thread_stack_str = thread_stack_str cmd.thread_suspend_str = thread_suspend_str return cmd except: return self.make_error_message(0, get_exception_traceback_str())
def do_it(self, dbg): try: res = pydevd_vars.custom_operation(dbg, self.thread_id, self.frame_id, self.scope, self.attrs, self.style, self.code_or_file, self.fnname) resEncoded = quote_plus(res) cmd = dbg.cmd_factory.make_custom_operation_message(self.sequence, resEncoded) dbg.writer.add_command(cmd) except: exc = get_exception_traceback_str() cmd = dbg.cmd_factory.make_error_message(self.sequence, "Error in running custom operation" + exc) dbg.writer.add_command(cmd)
def do_it(self, dbg): ''' Get completions and write back to the client ''' try: frame = dbg.find_frame(self.thread_id, self.frame_id) completions_xml = pydevd_console.get_completions(frame, self.act_tok) cmd = dbg.cmd_factory.make_send_console_message(self.sequence, completions_xml) dbg.writer.add_command(cmd) except: exc = get_exception_traceback_str() cmd = dbg.cmd_factory.make_error_message(self.sequence, "Error in fetching completions" + exc) dbg.writer.add_command(cmd)
def make_list_threads_message(self, seq): """ returns thread listing as XML """ try: threads = get_non_pydevd_threads() cmd_text = ["<xml>"] append = cmd_text.append for thread in threads: if is_thread_alive(thread): append(self._thread_to_xml(thread)) append("</xml>") return NetCommand(CMD_RETURN, seq, ''.join(cmd_text)) except: return self.make_error_message(seq, get_exception_traceback_str())
def internal_get_description(dbg, seq, thread_id, frame_id, expression): ''' Fetch the variable description stub from the debug console ''' try: frame = dbg.find_frame(thread_id, frame_id) description = pydevd_console.get_description(frame, thread_id, frame_id, expression) description = pydevd_xml.make_valid_xml_value(quote(description, '/>_= \t')) description_xml = '<xml><var name="" type="" value="%s"/></xml>' % description cmd = dbg.cmd_factory.make_get_description_message(seq, description_xml) dbg.writer.add_command(cmd) except: exc = get_exception_traceback_str() cmd = dbg.cmd_factory.make_error_message(seq, "Error in fetching description" + exc) dbg.writer.add_command(cmd)
def make_io_message(self, v, ctx): ''' @param v: the message to pass to the debug server @param ctx: 1 for stdio 2 for stderr ''' try: if len(v) > MAX_IO_MSG_SIZE: v = v[0:MAX_IO_MSG_SIZE] v += '...' v = pydevd_xml.make_valid_xml_value(quote(v, '/>_= ')) return NetCommand(str(CMD_WRITE_TO_CONSOLE), 0, '<xml><io s="%s" ctx="%s"/></xml>' % (v, ctx)) except: return self.make_error_message(0, get_exception_traceback_str())
def internal_evaluate_expression(dbg, seq, thread_id, frame_id, expression, is_exec, trim_if_too_big, attr_to_set_result): ''' gets the value of a variable ''' try: result = pydevd_vars.evaluate_expression(dbg, thread_id, frame_id, expression, is_exec) if attr_to_set_result != "": pydevd_vars.change_attr_expression(thread_id, frame_id, attr_to_set_result, expression, dbg, result) xml = "<xml>" xml += pydevd_xml.var_to_xml(result, expression, trim_if_too_big) xml += "</xml>" cmd = dbg.cmd_factory.make_evaluate_expression_message(seq, xml) dbg.writer.add_command(cmd) except: exc = get_exception_traceback_str() cmd = dbg.cmd_factory.make_error_message(seq, "Error evaluating expression " + exc) dbg.writer.add_command(cmd)
def request_load_source(self, py_db, seq, filename): ''' :param str filename: Note: must be already translated for the server. ''' try: assert filename.__class__ == str # i.e.: bytes on py2 and str on py3 with open(filename, 'r') as stream: source = stream.read() cmd = py_db.cmd_factory.make_load_source_message(seq, source) except: cmd = py_db.cmd_factory.make_error_message(seq, get_exception_traceback_str()) py_db.writer.add_command(cmd)
def internal_get_completions(dbg, seq, thread_id, frame_id, act_tok, line=-1, column=-1): ''' Note that if the column is >= 0, the act_tok is considered text and the actual activation token/qualifier is computed in this command. ''' try: remove_path = None try: qualifier = u'' if column >= 0: token_and_qualifier = extract_token_and_qualifier(act_tok, line, column) act_tok = token_and_qualifier[0] if act_tok: act_tok += u'.' qualifier = token_and_qualifier[1] frame = dbg.find_frame(thread_id, frame_id) if frame is not None: if IS_PY2: if not isinstance(act_tok, bytes): act_tok = act_tok.encode('utf-8') if not isinstance(qualifier, bytes): qualifier = qualifier.encode('utf-8') completions = _pydev_completer.generate_completions(frame, act_tok) # Note that qualifier and start are only actually valid for the # Debug Adapter Protocol (for the line-based protocol, the IDE # is required to filter the completions returned). cmd = dbg.cmd_factory.make_get_completions_message( seq, completions, qualifier, start=column - len(qualifier)) dbg.writer.add_command(cmd) else: cmd = dbg.cmd_factory.make_error_message(seq, "internal_get_completions: Frame not found: %s from thread: %s" % (frame_id, thread_id)) dbg.writer.add_command(cmd) finally: if remove_path is not None: sys.path.remove(remove_path) except: exc = get_exception_traceback_str() sys.stderr.write('%s\n' % (exc,)) cmd = dbg.cmd_factory.make_error_message(seq, "Error evaluating expression " + exc) dbg.writer.add_command(cmd)
def push(self, line, frame, buffer_output=True): """Change built-in stdout and stderr methods by the new custom StdMessage. execute the InteractiveConsole.push. Change the stdout and stderr back be the original built-ins :param buffer_output: if False won't redirect the output. Return boolean (True if more input is required else False), output_messages and input_messages """ self.__buffer_output = buffer_output more = False if buffer_output: original_stdout = sys.stdout original_stderr = sys.stderr try: try: self.frame = frame if buffer_output: out = sys.stdout = IOBuf() err = sys.stderr = IOBuf() more = self.add_exec(line) except Exception: exc = get_exception_traceback_str() if buffer_output: err.buflist.append("Internal Error: %s" % (exc,)) else: sys.stderr.write("Internal Error: %s\n" % (exc,)) finally: #Remove frame references. self.frame = None frame = None if buffer_output: sys.stdout = original_stdout sys.stderr = original_stderr if buffer_output: return more, out.buflist, err.buflist else: return more, [], []
def do_it(self, dbg): try: callstack = "<xml>" makeValid = pydevd_xml.make_valid_xml_value for filename, line, methodname, methodobj in self.stacktrace: if not filesystem_encoding_is_utf8 and hasattr(filename, "decode"): # filename is a byte string encoded using the file system encoding # convert it to utf8 filename = filename.decode(file_system_encoding).encode("utf-8") callstack += '<frame thread_id = "%s" file="%s" line="%s" name="%s" obj="%s" />' \ % (self.thread_id, makeValid(filename), line, makeValid(methodname), makeValid(methodobj)) callstack += "</xml>" cmd = dbg.cmd_factory.make_send_breakpoint_exception_message(self.sequence, self.exc_type + "\t" + callstack) dbg.writer.add_command(cmd) except: exc = get_exception_traceback_str() sys.stderr.write('%s\n' % (exc,)) cmd = dbg.cmd_factory.make_error_message(self.sequence, "Error Sending Exception: " + exc) dbg.writer.add_command(cmd)
def do_it(self, dbg): ''' Converts request into python variable ''' try: try: # don't trace new threads created by console command disable_trace_thread_modules() result = pydevconsole.console_exec(self.thread_id, self.frame_id, self.expression, dbg) xml = "<xml>" xml += pydevd_xml.var_to_xml(result, "") xml += "</xml>" cmd = dbg.cmd_factory.make_evaluate_expression_message(self.sequence, xml) dbg.writer.add_command(cmd) except: exc = get_exception_traceback_str() sys.stderr.write('%s\n' % (exc,)) cmd = dbg.cmd_factory.make_error_message(self.sequence, "Error evaluating console expression " + exc) dbg.writer.add_command(cmd) finally: enable_trace_thread_modules() sys.stderr.flush() sys.stdout.flush()
def do_it(self, dbg): '''Starts a thread that will load values asynchronously''' try: var_objects = [] for variable in self.vars: variable = variable.strip() if len(variable) > 0: if '\t' in variable: # there are attributes beyond scope scope, attrs = variable.split('\t', 1) name = attrs[0] else: scope, attrs = (variable, None) name = scope var_obj = pydevd_vars.getVariable(dbg, self.thread_id, self.frame_id, scope, attrs) var_objects.append((var_obj, name)) t = GetValueAsyncThreadDebug(dbg, self.sequence, var_objects) t.start() except: exc = get_exception_traceback_str() sys.stderr.write('%s\n' % (exc,)) cmd = dbg.cmd_factory.make_error_message(self.sequence, "Error evaluating variable %s " % exc) dbg.writer.add_command(cmd)
def make_thread_suspend_single_notification(self, py_db, thread_id, stop_reason): try: return NetCommand(CMD_THREAD_SUSPEND_SINGLE_NOTIFICATION, 0, json.dumps( {'thread_id': thread_id, 'stop_reason':stop_reason})) except: return self.make_error_message(0, get_exception_traceback_str())
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 make_load_full_value_message(self, seq, payload): try: return NetCommand(CMD_LOAD_FULL_VALUE, seq, payload) except Exception: return self.make_error_message(seq, get_exception_traceback_str())
def make_get_array_message(self, seq, payload): try: return NetCommand(CMD_GET_ARRAY, seq, payload) except Exception: return self.make_error_message(seq, get_exception_traceback_str())
def make_get_frame_message(self, seq, payload): try: return NetCommand(CMD_GET_FRAME, seq, payload) except Exception: return self.make_error_message(seq, get_exception_traceback_str())
def make_thread_killed_message(self, tid): try: return NetCommand(CMD_THREAD_KILL, 0, str(tid)) except: return self.make_error_message(0, get_exception_traceback_str())
def make_thread_run_message(self, thread_id, reason): try: return NetCommand(CMD_THREAD_RUN, 0, "%s\t%s" % (thread_id, reason)) except: return self.make_error_message(0, get_exception_traceback_str())
def make_input_requested_message(self, started): try: return NetCommand(CMD_INPUT_REQUESTED, 0, str(started)) except: return self.make_error_message(0, get_exception_traceback_str())
def make_reloaded_code_message(self, seq, reloaded_ok): try: return NetCommand(CMD_RELOAD_CODE, seq, '<xml><reloaded ok="%s"></reloaded></xml>' % reloaded_ok) except Exception: return self.make_error_message(seq, get_exception_traceback_str())
def make_get_next_statement_targets_message(self, seq, payload): try: return NetCommand(CMD_GET_NEXT_STATEMENT_TARGETS, seq, payload) except Exception: return self.make_error_message(seq, get_exception_traceback_str())
def make_show_cython_warning_message(self): try: return NetCommand(CMD_SHOW_CYTHON_WARNING, 0, '') except: return self.make_error_message(0, get_exception_traceback_str())
def do_it(self, dbg): ''' Converts request into python variable ''' try: result = pydevd_vars.change_attr_expression(self.thread_id, self.frame_id, self.attr, self.expression, dbg) xml = "<xml>" xml += pydevd_xml.var_to_xml(result, "") xml += "</xml>" cmd = dbg.cmd_factory.make_variable_changed_message(self.sequence, xml) dbg.writer.add_command(cmd) except Exception: cmd = dbg.cmd_factory.make_error_message(self.sequence, "Error changing variable attr:%s expression:%s traceback:%s" % (self.attr, self.expression, get_exception_traceback_str())) dbg.writer.add_command(cmd)
def do_it(self, dbg): try: frame = dbg.find_frame(self.thread_id, self.frame_id) var = pydevd_vars.eval_in_context(self.name, frame.f_globals, frame.f_locals) xml = pydevd_vars.table_like_struct_to_xml(var, self.name, self.roffset, self.coffset, self.rows, self.cols, self.format) cmd = dbg.cmd_factory.make_get_array_message(self.sequence, xml) dbg.writer.add_command(cmd) except: cmd = dbg.cmd_factory.make_error_message(self.sequence, "Error resolving array: " + get_exception_traceback_str()) dbg.writer.add_command(cmd)
def make_show_console_message(self, thread_id, frame): try: thread_suspended_str, _thread_stack_str = self.make_thread_suspend_str(thread_id, frame, CMD_SHOW_CONSOLE, '') return NetCommand(CMD_SHOW_CONSOLE, 0, thread_suspended_str) except: return self.make_error_message(0, get_exception_traceback_str())
def make_set_next_stmnt_status_message(self, seq, is_success, exception_msg): try: message = str(is_success) + '\t' + exception_msg return NetCommand(CMD_SET_NEXT_STATEMENT, int(seq), message) except: return self.make_error_message(0, get_exception_traceback_str())
def make_get_completions_message(self, seq, completions, qualifier, start): try: payload = completions_to_xml(completions) return NetCommand(CMD_GET_COMPLETIONS, seq, payload) except Exception: return self.make_error_message(seq, get_exception_traceback_str())
def make_thread_resume_single_notification(self, thread_id): try: return NetCommand(CMD_THREAD_RESUME_SINGLE_NOTIFICATION, 0, json.dumps({'thread_id': thread_id})) except: return self.make_error_message(0, get_exception_traceback_str())
def make_send_breakpoint_exception_message(self, seq, payload): try: return NetCommand(CMD_GET_BREAKPOINT_EXCEPTION, seq, payload) except Exception: return self.make_error_message(seq, get_exception_traceback_str())
def make_get_variable_message(self, seq, payload): try: return NetCommand(CMD_GET_VARIABLE, seq, payload) except Exception: return self.make_error_message(seq, get_exception_traceback_str())
def make_send_console_message(self, seq, payload): try: return NetCommand(CMD_EVALUATE_CONSOLE_EXPRESSION, seq, payload) except Exception: return self.make_error_message(seq, get_exception_traceback_str())
def make_get_description_message(self, seq, payload): try: return NetCommand(CMD_GET_DESCRIPTION, seq, payload) except Exception: return self.make_error_message(seq, get_exception_traceback_str())
def make_evaluate_expression_message(self, seq, payload): try: return NetCommand(CMD_EVALUATE_EXPRESSION, seq, payload) except Exception: return self.make_error_message(seq, get_exception_traceback_str())
def make_get_file_contents(self, seq, payload): try: return NetCommand(CMD_GET_FILE_CONTENTS, seq, payload) except Exception: return self.make_error_message(seq, get_exception_traceback_str())
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 in (CMD_RUN_TO_LINE, CMD_SET_NEXT_STATEMENT, CMD_SMART_STEP_INTO): if cmd_id == CMD_SMART_STEP_INTO: # we received a smart step into command thread_id, frame_id, line, func_name, call_order, start_line, end_line = text.split( '\t', 6) else: # we received some command to make a single step thread_id, line, func_name = text.split('\t', 2) if func_name == "None": # global context func_name = '' t = pydevd_find_thread_by_id(thread_id) if t: if cmd_id == CMD_SMART_STEP_INTO: int_cmd = InternalSmartStepInto( thread_id, frame_id, cmd_id, func_name, line, call_order, start_line, end_line, seq) else: int_cmd = InternalSetNextStatementThread( thread_id, cmd_id, line, func_name, seq) 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_SET_UNIT_TEST_DEBUGGING_MODE: py_db.set_unit_tests_debugging_mode() 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) if pydevd_file_utils.is_real_file(file): 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: if type == 'jupyter-line': return else: 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( ) if py_db.has_plugin_line_breaks: py_db.frame_eval_func = None 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) if pydevd_file_utils.is_real_file(file): 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(removed=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_PROCESS_CREATED_MSG_RECEIVED: original_seq = int(text) event = py_db.process_created_msg_received_events.pop( original_seq, None) if event: event.set() 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 elif cmd_id == CMD_GET_SMART_STEP_INTO_VARIANTS: thread_id, frame_id, start_line, end_line = text.split('\t', 3) int_cmd = InternalGetSmartStepIntoVariants( seq, thread_id, frame_id, start_line, end_line) py_db.post_internal_command(int_cmd, thread_id) # Powerful DataViewer commands elif cmd_id == CMD_DATAVIEWER_ACTION: # format: thread_id frame_id name temp try: thread_id, frame_id, var, action, args = text.split( '\t', 4) args = args.split('\t') int_cmd = InternalDataViewerAction(seq, thread_id, frame_id, var, action, args) py_db.post_internal_command(int_cmd, thread_id) except: traceback.print_exc() elif cmd_id == CMD_TABLE_EXEC: try: thread_id, frame_id, init_command, command_type = text.split( '\t', 3) int_cmd = InternalTableCommand(seq, thread_id, frame_id, init_command, command_type) py_db.post_internal_command(int_cmd, thread_id) except: traceback.print_exc() 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 make_send_curr_exception_trace_proceeded_message(self, seq, thread_id): try: return NetCommand(CMD_SEND_CURR_EXCEPTION_TRACE_PROCEEDED, 0, str(thread_id)) except: return self.make_error_message(0, get_exception_traceback_str())
def make_custom_operation_message(self, seq, payload): try: return NetCommand(CMD_RUN_CUSTOM_OPERATION, seq, payload) except Exception: return self.make_error_message(seq, get_exception_traceback_str())
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_VERSION: # response is version number # ide_os should be 'WINDOWS' or 'UNIX'. ide_os = 'WINDOWS' # 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_THREAD_KILL: int_cmd = InternalTerminateThread(text) py_db.post_internal_command(int_cmd, text) elif cmd_id == CMD_THREAD_SUSPEND: # Yes, thread suspend is still done at this point, not through an internal command! t = pydevd_find_thread_by_id(text) if t and not hasattr(t, 'pydev_do_not_trace'): additional_info = None try: additional_info = t.additional_info except AttributeError: pass # that's ok, no info currently set if additional_info is not None: for frame in additional_info.iter_frames(t): py_db.set_trace_for_frame_and_parents(frame, overwrite_prev_trace=True) del frame py_db.set_suspend(t, CMD_THREAD_SUSPEND) elif text.startswith('__frame__:'): sys.stderr.write("Can't suspend tasklet: %s\n" % (text,)) elif cmd_id == CMD_THREAD_RUN: t = pydevd_find_thread_by_id(text) if t: t.additional_info.pydev_step_cmd = -1 t.additional_info.pydev_step_stop = None t.additional_info.pydev_state = STATE_RUN elif text.startswith('__frame__:'): sys.stderr.write("Can't make tasklet run: %s\n" % (text,)) 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. # for tid, t in py_db._running_thread_ids.items(): #Iterate in copy # thread_name = t.getName() # # print thread_name, get_thread_id(t) # #Note: if possible, try to reload on the main thread # if thread_name == 'MainThread': # thread_id = tid 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_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" if py_db._set_breakpoints_with_id: 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 len(condition) <= 0 or condition is None or condition == "None": condition = None if len(expression) <= 0 or expression is None or expression == "None": expression = None if type == 'python-line': breakpoint = LineBreakpoint(line, condition, func_name, expression, suspend_policy) 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) 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 dict_contains(file_to_id_to_breakpoint, file): 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(overwrite_prev_trace=True) 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;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) >= 4: 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.break_on_exceptions_thrown_in_same_context = True else: py_db.break_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 for exception_type in splitted[4:]: exception_type = exception_type.strip() if not exception_type: continue exception_breakpoint = py_db.add_break_on_exception( exception_type, notify_always=break_on_caught, notify_on_terminate=break_on_uncaught, notify_on_first_raise_only=False, ) if exception_breakpoint is None: continue added.append(exception_breakpoint) py_db.update_after_exceptions_added(added) 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: if text.find('\t') != -1: exception, notify_always, notify_on_terminate, ignore_libraries = text.split('\t', 3) else: exception, notify_always, notify_on_terminate, ignore_libraries = text, 0, 0, 0 if exception.find('-') != -1: breakpoint_type, exception = exception.split('-') else: breakpoint_type = 'python' if breakpoint_type == 'python': if int(notify_always) == 1: pydev_log.warn("Deprecated parameter: 'notify always' policy removed in PyCharm\n") exception_breakpoint = py_db.add_break_on_exception( exception, notify_always=int(notify_always) > 0, notify_on_terminate = int(notify_on_terminate) == 1, notify_on_first_raise_only=int(notify_always) == 2, ignore_libraries=int(ignore_libraries) > 0 ) if exception_breakpoint is not None: py_db.update_after_exceptions_added([exception_breakpoint]) 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() 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() dict_pop(cp, exception, None) py_db.break_on_uncaught_exceptions = cp cp = py_db.break_on_caught_exceptions.copy() dict_pop(cp, exception, None) py_db.break_on_caught_exceptions = cp except: pydev_log.debug("Error while removing exception %s"%sys.exc_info()[0]) update_exception_hook(py_db) 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) elif cmd_id == CMD_LOAD_SOURCE: path = text try: f = open(path, 'r') source = f.read() py_db.cmd_factory.make_load_source_message(seq, source, py_db) except: return 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() 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() 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) 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() from _pydev_bundle.pydev_imports 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 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_VERSION: # response is version number # ide_os should be 'WINDOWS' or 'UNIX'. ide_os = 'WINDOWS' # 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_THREAD_KILL: int_cmd = InternalTerminateThread(text) py_db.post_internal_command(int_cmd, text) elif cmd_id == CMD_THREAD_SUSPEND: # Yes, thread suspend is still done at this point, not through an internal command! t = pydevd_find_thread_by_id(text) if t and not hasattr(t, 'pydev_do_not_trace'): additional_info = None try: additional_info = t.additional_info except AttributeError: pass # that's ok, no info currently set if additional_info is not None: for frame in additional_info.iter_frames(t): py_db.set_trace_for_frame_and_parents( frame, overwrite_prev_trace=True) del frame py_db.set_suspend(t, CMD_THREAD_SUSPEND) elif text.startswith('__frame__:'): sys.stderr.write("Can't suspend tasklet: %s\n" % (text, )) elif cmd_id == CMD_THREAD_RUN: t = pydevd_find_thread_by_id(text) if t: t.additional_info.pydev_step_cmd = -1 t.additional_info.pydev_step_stop = None t.additional_info.pydev_state = STATE_RUN elif text.startswith('__frame__:'): sys.stderr.write("Can't make tasklet run: %s\n" % (text, )) 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. # for tid, t in py_db._running_thread_ids.items(): #Iterate in copy # thread_name = t.getName() # # print thread_name, get_thread_id(t) # #Note: if possible, try to reload on the main thread # if thread_name == 'MainThread': # thread_id = tid 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_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" if py_db._set_breakpoints_with_id: 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 len(condition ) <= 0 or condition is None or condition == "None": condition = None if len(expression ) <= 0 or expression is None or expression == "None": expression = None if type == 'python-line': breakpoint = LineBreakpoint(line, condition, func_name, expression, suspend_policy) 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) 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( overwrite_prev_trace=True) 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;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) >= 4: 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.break_on_exceptions_thrown_in_same_context = True else: py_db.break_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 for exception_type in splitted[4:]: exception_type = exception_type.strip() if not exception_type: continue exception_breakpoint = py_db.add_break_on_exception( exception_type, notify_always=break_on_caught, notify_on_terminate=break_on_uncaught, notify_on_first_raise_only=False, ) if exception_breakpoint is None: continue added.append(exception_breakpoint) py_db.update_after_exceptions_added(added) 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: if text.find('\t') != -1: exception, notify_always, notify_on_terminate, ignore_libraries = text.split( '\t', 3) else: exception, notify_always, notify_on_terminate, ignore_libraries = text, 0, 0, 0 if exception.find('-') != -1: breakpoint_type, exception = exception.split('-') else: breakpoint_type = 'python' if breakpoint_type == 'python': if int(notify_always) == 1: pydev_log.warn( "Deprecated parameter: 'notify always' policy removed in PyCharm\n" ) exception_breakpoint = py_db.add_break_on_exception( exception, notify_always=int(notify_always) > 0, notify_on_terminate=int(notify_on_terminate) == 1, notify_on_first_raise_only=int(notify_always) == 2, ignore_libraries=int(ignore_libraries) > 0) if exception_breakpoint is not None: py_db.update_after_exceptions_added( [exception_breakpoint]) 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( ) 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]) update_exception_hook(py_db) 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) elif cmd_id == CMD_LOAD_SOURCE: path = text try: f = open(path, 'r') source = f.read() py_db.cmd_factory.make_load_source_message( seq, source, py_db) except: return 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( ) 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( ) 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) 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() from _pydev_bundle.pydev_imports 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 make_version_message(self, seq): try: return NetCommand(CMD_VERSION, seq, VERSION_STRING) except: return self.make_error_message(seq, get_exception_traceback_str())
def make_thread_killed_message(self, tid): self._additional_thread_id_to_thread_name.pop(tid, None) try: return NetCommand(CMD_THREAD_KILL, 0, str(tid)) except: return self.make_error_message(0, get_exception_traceback_str())