def _is_django_render_call(frame): try: name = frame.f_code.co_name if name != 'render': return False if not dict_contains(frame.f_locals, 'self'): return False cls = frame.f_locals['self'].__class__ inherits_node = _inherits(cls, 'Node') if not inherits_node: return False clsname = cls.__name__ if IS_DJANGO19: # in Django 1.9 we need to save the flag that there is included template if clsname == 'IncludeNode': if dict_contains(frame.f_locals, 'context'): context = frame.f_locals['context'] context._has_included_template = True return clsname != 'TextNode' and clsname != 'NodeList' except: traceback.print_exc() return False
def default_should_trace_hook(frame, filename): ''' Return True if this frame should be traced, False if tracing should be blocked. ''' # First, check whether this code object has a cached value ignored_lines = _filename_to_ignored_lines.get(filename) if ignored_lines is None: # Now, look up that line of code and check for a @DontTrace # preceding or on the same line as the method. # E.g.: # #@DontTrace # def test(): # pass # ... or ... # def test(): #@DontTrace # pass ignored_lines = {} lines = linecache.getlines(filename) i_line = 0 # Could use enumerate, but not there on all versions... for line in lines: j = line.find('#') if j >= 0: comment = line[j:] if DONT_TRACE_TAG in comment: ignored_lines[i_line] = 1 #Note: when it's found in the comment, mark it up and down for the decorator lines found. k = i_line - 1 while k >= 0: if RE_DECORATOR.match(lines[k]): ignored_lines[k] = 1 k -= 1 else: break k = i_line + 1 while k <= len(lines): if RE_DECORATOR.match(lines[k]): ignored_lines[k] = 1 k += 1 else: break i_line += 1 _filename_to_ignored_lines[filename] = ignored_lines func_line = frame.f_code.co_firstlineno - 1 # co_firstlineno is 1-based, so -1 is needed return not ( dict_contains(ignored_lines, func_line - 1) or #-1 to get line before method dict_contains(ignored_lines, func_line)) #method line
def get_breakpoint(plugin, pydb, pydb_frame, frame, event, args): pydb = args[0] filename = args[1] info = args[2] new_frame = None jinja2_breakpoint = None flag = False type = 'jinja2' if event in ('line', 'call') and info.pydev_state != STATE_SUSPEND and \ pydb.jinja2_breakpoints and _is_jinja2_render_call(frame): filename = _get_jinja2_template_filename(frame) jinja2_breakpoints_for_file = pydb.jinja2_breakpoints.get(filename) new_frame = Jinja2TemplateFrame(frame) if jinja2_breakpoints_for_file: lineno = frame.f_lineno template_lineno = _get_jinja2_template_line(frame) if template_lineno is not None and dict_contains( jinja2_breakpoints_for_file, template_lineno): jinja2_breakpoint = jinja2_breakpoints_for_file[ template_lineno] flag = True new_frame = Jinja2TemplateFrame(frame) return flag, jinja2_breakpoint, new_frame, type
def _schedule_callback(prev, next): ''' Called when a context is stopped or a new context is made runnable. ''' try: if not prev and not next: return if next: register_tasklet_info(next) # Ok, making next runnable: set the tracing facility in it. debugger = get_global_debugger() if debugger is not None and next.frame: if hasattr(next.frame, 'f_trace'): next.frame.f_trace = debugger.trace_dispatch debugger = None if prev: register_tasklet_info(prev) try: for tasklet_ref, tasklet_info in dict_items(_weak_tasklet_registered_to_info): # Make sure it's a copy! tasklet = tasklet_ref() if tasklet is None or not tasklet.alive: # Garbage-collected already! try: del _weak_tasklet_registered_to_info[tasklet_ref] except KeyError: pass if tasklet_info.frame_id is not None: remove_custom_frame(tasklet_info.frame_id) else: if tasklet.paused or tasklet.blocked or tasklet.scheduled: if tasklet.frame and tasklet.frame.f_back: f_back = tasklet.frame.f_back base = get_abs_path_real_path_and_base_from_frame(f_back)[-1] is_file_to_ignore = dict_contains(DONT_TRACE, base) if not is_file_to_ignore: if tasklet_info.frame_id is None: tasklet_info.frame_id = add_custom_frame(f_back, tasklet_info.tasklet_name, tasklet.thread_id) else: update_custom_frame(tasklet_info.frame_id, f_back, tasklet.thread_id) elif tasklet.is_current: if tasklet_info.frame_id is not None: # Remove info about stackless suspended when it starts to run. remove_custom_frame(tasklet_info.frame_id) tasklet_info.frame_id = None finally: tasklet = None tasklet_info = None f_back = None except: import traceback;traceback.print_exc() if _application_set_schedule_callback is not None: return _application_set_schedule_callback(prev, next)
def frame_vars_to_xml(frame_f_locals, hidden_ns=None): """ dumps frame variables to XML <var name="var_name" scope="local" type="type" value="value"/> """ xml = "" keys = dict_keys(frame_f_locals) if hasattr(keys, 'sort'): keys.sort() #Python 3.0 does not have it else: keys = sorted(keys) #Jython 2.1 does not have it return_values_xml = '' for k in keys: try: v = frame_f_locals[k] if k == RETURN_VALUES_DICT: for name, val in dict_iter_items(v): return_values_xml += var_to_xml(val, name, additional_in_xml=' isRetVal="True"') else: if hidden_ns is not None and dict_contains(hidden_ns, k): xml += var_to_xml(v, str(k), additional_in_xml=' isIPythonHidden="True"') else: xml += var_to_xml(v, str(k)) except Exception: traceback.print_exc() pydev_log.error("Unexpected error, recovered safely.\n") # Show return values as the first entry. return return_values_xml + xml
def frame_vars_to_xml(frame_f_locals, hidden_ns=None): """ dumps frame variables to XML <var name="var_name" scope="local" type="type" value="value"/> """ xml = "" keys = dict_keys(frame_f_locals) if hasattr(keys, 'sort'): keys.sort() #Python 3.0 does not have it else: keys = sorted(keys) #Jython 2.1 does not have it for k in keys: try: v = frame_f_locals[k] if k == RETURN_VALUES_DICT: xml += return_values_from_dict_to_xml(v) else: if hidden_ns is not None and dict_contains(hidden_ns, k): xml += var_to_xml( v, str(k), additionalInXml=' isIPythonHidden="True"') else: xml += var_to_xml(v, str(k)) except Exception: traceback.print_exc() pydev_log.error("Unexpected error, recovered safely.\n") return xml
def get_breakpoint(plugin, main_debugger, pydb_frame, frame, event, args): main_debugger = args[0] filename = args[1] info = args[2] flag = False django_breakpoint = None new_frame = None type = 'django' if event == 'call' and info.pydev_state != STATE_SUSPEND and \ main_debugger.django_breakpoints and _is_django_render_call(frame): filename = _get_template_file_name(frame) pydev_log.debug("Django is rendering a template: %s\n" % filename) django_breakpoints_for_file = main_debugger.django_breakpoints.get( filename) if django_breakpoints_for_file: pydev_log.debug("Breakpoints for that file: %s\n" % django_breakpoints_for_file) template_line = _get_template_line(frame) pydev_log.debug("Tracing template line: %s\n" % str(template_line)) if dict_contains(django_breakpoints_for_file, template_line): django_breakpoint = django_breakpoints_for_file[template_line] flag = True new_frame = DjangoTemplateFrame(frame) return flag, django_breakpoint, new_frame, type
def _get_template_file_name(frame): try: if IS_DJANGO19_OR_HIGHER: # The Node source was removed since Django 1.9 if dict_contains(frame.f_locals, 'context'): context = frame.f_locals['context'] if hasattr(context, 'template') and hasattr(context.template, 'origin') and \ hasattr(context.template.origin, 'name'): return context.template.origin.name return None source = _get_source_django_18_or_lower(frame) if source is None: pydev_log.debug("Source is None\n") return None fname = source[0].name if fname == '<unknown source>': pydev_log.debug("Source name is %s\n" % fname) return None else: abs_path_real_path_and_base = get_abs_path_real_path_and_base_from_file(fname) return abs_path_real_path_and_base[1] except: pydev_log.debug(traceback.format_exc()) return None
def _get_jinja2_template_filename(frame): if dict_contains(frame.f_globals, '__jinja_template__'): fname = frame.f_globals['__jinja_template__'].filename abs_path_real_path_and_base = get_abs_path_real_path_and_base_from_file( fname) return abs_path_real_path_and_base[1] return None
def _get_template_file_name(frame): try: if IS_DJANGO19_OR_HIGHER: # The Node source was removed since Django 1.9 if dict_contains(frame.f_locals, 'context'): context = frame.f_locals['context'] if hasattr(context, 'template') and hasattr(context.template, 'origin') and \ hasattr(context.template.origin, 'name'): return context.template.origin.name return None source = _get_source_django_18_or_lower(frame) if source is None: pydev_log.debug("Source is None\n") return None fname = source[0].name if fname == '<unknown source>': pydev_log.debug("Source name is %s\n" % fname) return None else: abs_path_real_path_and_base = get_abs_path_real_path_and_base_from_file( fname) return abs_path_real_path_and_base[1] except: pydev_log.debug(traceback.format_exc()) return None
def _get_template_file_name(frame): try: if IS_DJANGO19: # The Node source was removed since Django 1.9 if dict_contains(frame.f_locals, 'context'): context = frame.f_locals['context'] if hasattr(context, '_has_included_template'): # if there was included template we need to inspect the previous frames and find its name back = frame.f_back while back is not None and frame.f_code.co_name in ( 'render', '_render'): locals = back.f_locals if dict_contains(locals, 'self'): self = locals['self'] if self.__class__.__name__ == 'Template' and hasattr(self, 'origin') and \ hasattr(self.origin, 'name'): return self.origin.name back = back.f_back else: if hasattr(context, 'template') and hasattr(context.template, 'origin') and \ hasattr(context.template.origin, 'name'): return normcase(context.template.origin.name) return None elif IS_DJANGO19_OR_HIGHER: # For Django 1.10 and later there is much simpler way to get template name if dict_contains(frame.f_locals, 'self'): self = frame.f_locals['self'] if hasattr(self, 'origin') and hasattr(self.origin, 'name'): return normcase(self.origin.name) return None source = _get_source_django_18_or_lower(frame) if source is None: pydev_log.debug("Source is None\n") return None fname = source[0].name if fname == '<unknown source>': pydev_log.debug("Source name is %s\n" % fname) return None else: abs_path_real_path_and_base = get_abs_path_real_path_and_base_from_file( fname) return abs_path_real_path_and_base[1] except: pydev_log.debug(traceback.format_exc()) return None
def stop(plugin, pydb, frame, event, args, stop_info, arg, step_cmd): pydb, filename, info, thread = args if dict_contains(stop_info, 'jinja2_stop') and stop_info['jinja2_stop']: frame = _suspend_jinja2(pydb, thread, frame, step_cmd) if frame: pydb.do_wait_suspend(thread, frame, event, arg) return True return False
def stop(plugin, main_debugger, frame, event, args, stop_info, arg, step_cmd): main_debugger, filename, info, thread = args if dict_contains(stop_info, 'django_stop') and stop_info['django_stop']: frame = suspend_django(main_debugger, thread, frame, step_cmd) if frame: main_debugger.do_wait_suspend(thread, frame, event, arg) return True return False
def _get_template_file_name(frame): try: if IS_DJANGO19: # The Node source was removed since Django 1.9 if dict_contains(frame.f_locals, 'context'): context = frame.f_locals['context'] if hasattr(context, '_has_included_template'): # if there was included template we need to inspect the previous frames and find its name back = frame.f_back while back is not None and frame.f_code.co_name in ('render', '_render'): locals = back.f_locals if dict_contains(locals, 'self'): self = locals['self'] if self.__class__.__name__ == 'Template' and hasattr(self, 'origin') and \ hasattr(self.origin, 'name'): return self.origin.name back = back.f_back else: if hasattr(context, 'template') and hasattr(context.template, 'origin') and \ hasattr(context.template.origin, 'name'): return normcase(context.template.origin.name) return None elif IS_DJANGO19_OR_HIGHER: # For Django 1.10 and later there is much simpler way to get template name if dict_contains(frame.f_locals, 'self'): self = frame.f_locals['self'] if hasattr(self, 'origin') and hasattr(self.origin, 'name'): return normcase(self.origin.name) return None source = _get_source_django_18_or_lower(frame) if source is None: pydev_log.debug("Source is None\n") return None fname = source[0].name if fname == '<unknown source>': pydev_log.debug("Source name is %s\n" % fname) return None else: abs_path_real_path_and_base = get_abs_path_real_path_and_base_from_file(fname) return abs_path_real_path_and_base[1] except: pydev_log.debug(traceback.format_exc()) return None
def _is_jinja2_render_call(frame): try: name = frame.f_code.co_name if dict_contains(frame.f_globals, "__jinja_template__") and name in ("root", "loop", "macro") or name.startswith("block_"): return True return False except: traceback.print_exc() return False
def get_task_id(self, frame): while frame is not None: if dict_contains(frame.f_locals, "self"): self_obj = frame.f_locals["self"] if isinstance(self_obj, asyncio.Task): method_name = frame.f_code.co_name if method_name == "_step": return id(self_obj) frame = frame.f_back return None
def _is_django_context_get_call(frame): try: if not dict_contains(frame.f_locals, 'self'): return False cls = frame.f_locals['self'].__class__ return _inherits(cls, 'BaseContext') except: traceback.print_exc() return False
def do_import(self, name, *args, **kwargs): activate_func = None if dict_contains(self._modules_to_patch, name): activate_func = self._modules_to_patch.pop(name) module = self._system_import(name, *args, **kwargs) try: if activate_func: activate_func() #call activate function except: sys.stderr.write("Matplotlib support failed\n") return module
def _find_render_function_frame(frame): #in order to hide internal rendering functions old_frame = frame try: while not (dict_contains(frame.f_locals, 'self') and frame.f_locals['self'].__class__.__name__ == 'Template' and \ frame.f_code.co_name == 'render'): frame = frame.f_back if frame is None: return old_frame return frame except: return old_frame
def _is_django_resolve_call(frame): try: name = frame.f_code.co_name if name != '_resolve_lookup': return False if not dict_contains(frame.f_locals, 'self'): return False cls = frame.f_locals['self'].__class__ clsname = cls.__name__ return clsname == 'Variable' except: traceback.print_exc() return False
def _get_jinja2_template_line(frame): debug_info = None if dict_contains(frame.f_globals,'__jinja_template__'): _debug_info = frame.f_globals['__jinja_template__']._debug_info if _debug_info != '': #sometimes template contains only plain text debug_info = frame.f_globals['__jinja_template__'].debug_info if debug_info is None: return None lineno = frame.f_lineno for pair in debug_info: if pair[1] == lineno: return pair[0] return None
def _get_jinja2_template_line(frame): debug_info = None if dict_contains(frame.f_globals, '__jinja_template__'): _debug_info = frame.f_globals['__jinja_template__']._debug_info if _debug_info != '': #sometimes template contains only plain text debug_info = frame.f_globals['__jinja_template__'].debug_info if debug_info is None: return None lineno = frame.f_lineno for pair in debug_info: if pair[1] == lineno: return pair[0] return None
def cmd_step_over(plugin, pydb, frame, event, args, stop_info, stop): info = args[2] thread = args[3] plugin_stop = False stop_info['jinja2_stop'] = False if _is_jinja2_suspended(thread): stop = False if info.pydev_call_inside_jinja2 is None: if _is_jinja2_render_call(frame): if event == 'call': info.pydev_call_inside_jinja2 = frame.f_back if event in ('line', 'return'): info.pydev_call_inside_jinja2 = frame else: if event == 'line': if _is_jinja2_render_call( frame) and info.pydev_call_inside_jinja2 is frame: stop_info['jinja2_stop'] = True plugin_stop = stop_info['jinja2_stop'] if event == 'return': if frame is info.pydev_call_inside_jinja2 and not dict_contains( frame.f_back.f_locals, 'event'): info.pydev_call_inside_jinja2 = _find_jinja2_render_frame( frame.f_back) return stop, plugin_stop else: if event == 'return' and _is_jinja2_context_call(frame.f_back): #we return from python code to Jinja2 rendering frame info.pydev_call_from_jinja2 = None info.pydev_call_inside_jinja2 = _find_jinja2_render_frame(frame) thread.additional_info.suspend_type = JINJA2_SUSPEND stop = False return stop, plugin_stop #print "info.pydev_call_from_jinja2", info.pydev_call_from_jinja2, "stop", stop, "jinja_stop", jinja2_stop, \ # "thread.additional_info.suspend_type", thread.additional_info.suspend_type #print "event", event, "info.pydev_call_inside_jinja2", info.pydev_call_inside_jinja2 #print "frame", frame, "frame.f_back", frame.f_back, "step_stop", info.pydev_step_stop #print "is_context_call", _is_jinja2_context_call(frame) #print "render", _is_jinja2_render_call(frame) #print "-------------" return stop, plugin_stop
def cmd_step_over(plugin, pydb, frame, event, args, stop_info, stop): pydb, filename, info, thread = args plugin_stop = False stop_info['jinja2_stop'] = False if not hasattr(info, 'pydev_call_from_jinja2'): info.pydev_call_from_jinja2 = None if not hasattr(info, 'pydev_call_inside_jinja2'): info.pydev_call_inside_jinja2 = None if _is_jinja2_suspended(thread): stop = False if info.pydev_call_inside_jinja2 is None: if _is_jinja2_render_call(frame): if event == 'call': info.pydev_call_inside_jinja2 = frame.f_back if event in ('line', 'return'): info.pydev_call_inside_jinja2 = frame else: if event == 'line': if _is_jinja2_render_call(frame) and info.pydev_call_inside_jinja2 is frame: stop_info['jinja2_stop'] = True plugin_stop = stop_info['jinja2_stop'] if event == 'return': if frame is info.pydev_call_inside_jinja2 and not dict_contains(frame.f_back.f_locals,'event'): info.pydev_call_inside_jinja2 = _find_jinja2_render_frame(frame.f_back) return stop, plugin_stop else: if event == 'return' and _is_jinja2_context_call(frame.f_back): #we return from python code to Jinja2 rendering frame info.pydev_call_from_jinja2 = None info.pydev_call_inside_jinja2 = _find_jinja2_render_frame(frame) thread.additional_info.suspend_type = JINJA2_SUSPEND stop = False return stop, plugin_stop #print "info.pydev_call_from_jinja2", info.pydev_call_from_jinja2, "stop", stop, "jinja_stop", jinja2_stop, \ # "thread.additional_info.suspend_type", thread.additional_info.suspend_type #print "event", event, "info.pydev_call_inside_jinja2", info.pydev_call_inside_jinja2 #print "frame", frame, "frame.f_back", frame.f_back, "step_stop", info.pydev_step_stop #print "is_context_call", _is_jinja2_context_call(frame) #print "render", _is_jinja2_render_call(frame) #print "-------------" return stop, plugin_stop
def get_breakpoint(plugin, pydb, pydb_frame, frame, event, args): pydb, filename, info, thread = args new_frame = None jinja2_breakpoint = None flag = False type = 'jinja2' if event in ('line', 'call') and info.pydev_state != STATE_SUSPEND and \ pydb.jinja2_breakpoints and _is_jinja2_render_call(frame): filename = _get_jinja2_template_filename(frame) jinja2_breakpoints_for_file = pydb.jinja2_breakpoints.get(filename) new_frame = Jinja2TemplateFrame(frame) if jinja2_breakpoints_for_file: lineno = frame.f_lineno template_lineno = _get_jinja2_template_line(frame) if template_lineno is not None and dict_contains(jinja2_breakpoints_for_file, template_lineno): jinja2_breakpoint = jinja2_breakpoints_for_file[template_lineno] flag = True new_frame = Jinja2TemplateFrame(frame) return flag, jinja2_breakpoint, new_frame, type
def _is_django_render_call(frame): try: name = frame.f_code.co_name if name != 'render': return False if not dict_contains(frame.f_locals, 'self'): return False cls = frame.f_locals['self'].__class__ inherits_node = _inherits(cls, 'Node') if not inherits_node: return False clsname = cls.__name__ return clsname != 'TextNode' and clsname != 'NodeList' except: traceback.print_exc() return False
def get_breakpoint(plugin, main_debugger, pydb_frame, frame, event, args): main_debugger, filename, info, thread = args flag = False django_breakpoint = None new_frame = None type = 'django' if event == 'call' and info.pydev_state != STATE_SUSPEND and \ main_debugger.django_breakpoints and _is_django_render_call(frame): filename = _get_template_file_name(frame) pydev_log.debug("Django is rendering a template: %s\n" % filename) django_breakpoints_for_file = main_debugger.django_breakpoints.get(filename) if django_breakpoints_for_file: pydev_log.debug("Breakpoints for that file: %s\n" % django_breakpoints_for_file) template_line = _get_template_line(frame) pydev_log.debug("Tracing template line: %d\n" % template_line) if dict_contains(django_breakpoints_for_file, template_line): django_breakpoint = django_breakpoints_for_file[template_line] flag = True new_frame = DjangoTemplateFrame(frame) return flag, django_breakpoint, new_frame, type
def has_additional_frames_by_id(thread_id): return dict_contains(AdditionalFramesContainer.additional_frames, thread_id)
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_if_not_frame_eval( overwrite_prev_trace=True) py_db.enable_tracing_in_frames_while_running_if_frame_eval() elif cmd_id == CMD_REMOVE_BREAK: #command to remove some breakpoint #text is type\file\tid. Remove from breakpoints dictionary breakpoint_type, file, breakpoint_id = text.split('\t', 2) if not IS_PY3K: # In Python 3, the frame object will have unicode for the file, whereas on python 2 it has a byte-array encoded with the filesystem encoding. file = file.encode(file_system_encoding) file = pydevd_file_utils.norm_file_to_server(file) try: breakpoint_id = int(breakpoint_id) except ValueError: pydev_log.error( 'Error removing breakpoint. Expected breakpoint_id to be an int. Found: %s' % (breakpoint_id, )) else: file_to_id_to_breakpoint = None if breakpoint_type == 'python-line': breakpoints = py_db.breakpoints file_to_id_to_breakpoint = py_db.file_to_id_to_line_breakpoint elif py_db.get_plugin_lazy_init() is not None: result = py_db.plugin.get_breakpoints( py_db, breakpoint_type) if result is not None: file_to_id_to_breakpoint = py_db.file_to_id_to_plugin_breakpoint breakpoints = result if file_to_id_to_breakpoint is None: pydev_log.error( 'Error removing breakpoint. Cant handle breakpoint of type %s' % breakpoint_type) else: try: id_to_pybreakpoint = file_to_id_to_breakpoint.get( file, {}) if DebugInfoHolder.DEBUG_TRACE_BREAKPOINTS > 0: existing = id_to_pybreakpoint[breakpoint_id] sys.stderr.write( 'Removed breakpoint:%s - line:%s - func_name:%s (id: %s)\n' % (file, existing.line, existing.func_name.encode('utf-8'), breakpoint_id)) del id_to_pybreakpoint[breakpoint_id] py_db.consolidate_breakpoints( file, id_to_pybreakpoint, breakpoints) if py_db.plugin is not None: py_db.has_plugin_line_breaks = py_db.plugin.has_line_breaks( ) except KeyError: pydev_log.error( "Error removing breakpoint: Breakpoint id not found: %s id: %s. Available ids: %s\n" % (file, breakpoint_id, dict_keys(id_to_pybreakpoint))) elif cmd_id == CMD_EVALUATE_EXPRESSION or cmd_id == CMD_EXEC_EXPRESSION: #command to evaluate the given expression #text is: thread\tstackframe\tLOCAL\texpression temp_name = "" try: thread_id, frame_id, scope, expression, trim, temp_name = text.split( '\t', 5) except ValueError: thread_id, frame_id, scope, expression, trim = text.split( '\t', 4) int_cmd = InternalEvaluateExpression( seq, thread_id, frame_id, expression, cmd_id == CMD_EXEC_EXPRESSION, int(trim) == 1, temp_name) py_db.post_internal_command(int_cmd, thread_id) elif cmd_id == CMD_CONSOLE_EXEC: #command to exec expression in console, in case expression is only partially valid 'False' is returned #text is: thread\tstackframe\tLOCAL\texpression thread_id, frame_id, scope, expression = text.split('\t', 3) int_cmd = InternalConsoleExec(seq, thread_id, frame_id, expression) py_db.post_internal_command(int_cmd, thread_id) elif cmd_id == CMD_SET_PY_EXCEPTION: # Command which receives set of exceptions on which user wants to break the debugger # text is: break_on_uncaught;break_on_caught;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) if break_on_caught: py_db.enable_tracing_in_frames_while_running_if_frame_eval( ) else: sys.stderr.write( "Error when setting exception list. Received: %s\n" % (text, )) elif cmd_id == CMD_GET_FILE_CONTENTS: if not IS_PY3K: # In Python 3, the frame object will have unicode for the file, whereas on python 2 it has a byte-array encoded with the filesystem encoding. text = text.encode(file_system_encoding) if os.path.exists(text): f = open(text, 'r') try: source = f.read() finally: f.close() cmd = py_db.cmd_factory.make_get_file_contents(seq, source) elif cmd_id == CMD_SET_PROPERTY_TRACE: # Command which receives whether to trace property getter/setter/deleter # text is feature_state(true/false);disable_getter/disable_setter/disable_deleter if text != "": splitted = text.split(';') if len(splitted) >= 3: if py_db.disable_property_trace is False and splitted[ 0] == 'true': # Replacing property by custom property only when the debugger starts pydevd_traceproperty.replace_builtin_property() py_db.disable_property_trace = True # Enable/Disable tracing of the property getter if splitted[1] == 'true': py_db.disable_property_getter_trace = True else: py_db.disable_property_getter_trace = False # Enable/Disable tracing of the property setter if splitted[2] == 'true': py_db.disable_property_setter_trace = True else: py_db.disable_property_setter_trace = False # Enable/Disable tracing of the property deleter if splitted[3] == 'true': py_db.disable_property_deleter_trace = True else: py_db.disable_property_deleter_trace = False else: # User hasn't configured any settings for property tracing pass elif cmd_id == CMD_ADD_EXCEPTION_BREAK: 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]) if notify_always: py_db.enable_tracing_in_frames_while_running_if_frame_eval( ) else: supported_type = False plugin = py_db.get_plugin_lazy_init() if plugin is not None: supported_type = plugin.add_breakpoint( 'add_exception_breakpoint', py_db, breakpoint_type, exception) if supported_type: py_db.has_plugin_exception_breaks = py_db.plugin.has_exception_breaks( ) py_db.enable_tracing_in_frames_while_running_if_frame_eval( ) else: raise NameError(breakpoint_type) elif cmd_id == CMD_REMOVE_EXCEPTION_BREAK: exception = text if exception.find('-') != -1: exception_type, exception = exception.split('-') else: exception_type = 'python' if exception_type == 'python': try: cp = py_db.break_on_uncaught_exceptions.copy() cp.pop(exception, None) py_db.break_on_uncaught_exceptions = cp cp = py_db.break_on_caught_exceptions.copy() cp.pop(exception, None) py_db.break_on_caught_exceptions = cp except: pydev_log.debug("Error while removing exception %s" % sys.exc_info()[0]) 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) if len(py_db.break_on_caught_exceptions ) == 0 and not py_db.has_plugin_exception_breaks: py_db.disable_tracing_while_running_if_frame_eval() elif cmd_id == CMD_LOAD_SOURCE: path = text try: 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( ) py_db.enable_tracing_in_frames_while_running_if_frame_eval( ) elif cmd_id == CMD_REMOVE_DJANGO_EXCEPTION_BREAK: exception = text # I.e.: no need to initialize lazy (if we didn't have it in the first place, we can't remove # anything from it anyways). plugin = py_db.plugin if plugin is not None: plugin.remove_exception_breakpoint(py_db, 'django', exception) py_db.has_plugin_exception_breaks = py_db.plugin.has_exception_breaks( ) if len(py_db.break_on_caught_exceptions ) == 0 and not py_db.has_plugin_exception_breaks: py_db.disable_tracing_while_running_if_frame_eval() elif cmd_id == CMD_EVALUATE_CONSOLE_EXPRESSION: # Command which takes care for the debug console communication if text != "": thread_id, frame_id, console_command = text.split('\t', 2) console_command, line = console_command.split('\t') if console_command == 'EVALUATE': int_cmd = InternalEvaluateConsoleExpression( seq, thread_id, frame_id, line, buffer_output=True) elif console_command == 'EVALUATE_UNBUFFERED': int_cmd = InternalEvaluateConsoleExpression( seq, thread_id, frame_id, line, buffer_output=False) elif console_command == 'GET_COMPLETIONS': int_cmd = InternalConsoleGetCompletions( seq, thread_id, frame_id, line) else: raise ValueError('Unrecognized command: %s' % (console_command, )) py_db.post_internal_command(int_cmd, thread_id) elif cmd_id == CMD_RUN_CUSTOM_OPERATION: # Command which runs a custom operation if text != "": try: location, custom = text.split('||', 1) except: sys.stderr.write( 'Custom operation now needs a || separator. Found: %s\n' % (text, )) raise thread_id, frame_id, scopeattrs = location.split('\t', 2) if scopeattrs.find( '\t') != -1: # there are attributes beyond scope scope, attrs = scopeattrs.split('\t', 1) else: scope, attrs = (scopeattrs, None) # : style: EXECFILE or EXEC # : encoded_code_or_file: file to execute or code # : fname: name of function to be executed in the resulting namespace style, encoded_code_or_file, fnname = custom.split('\t', 3) int_cmd = InternalRunCustomOperation( seq, thread_id, frame_id, scope, attrs, style, encoded_code_or_file, fnname) py_db.post_internal_command(int_cmd, thread_id) elif cmd_id == CMD_IGNORE_THROWN_EXCEPTION_AT: if text: replace = 'REPLACE:' # Not all 3.x versions support u'REPLACE:', so, doing workaround. if not IS_PY3K: replace = unicode(replace) if text.startswith(replace): text = text[8:] py_db.filename_to_lines_where_exceptions_are_ignored.clear( ) if text: for line in text.split( '||' ): # Can be bulk-created (one in each line) filename, line_number = line.split('|') if not IS_PY3K: filename = filename.encode( file_system_encoding) filename = pydevd_file_utils.norm_file_to_server( filename) if os.path.exists(filename): lines_ignored = py_db.filename_to_lines_where_exceptions_are_ignored.get( filename) if lines_ignored is None: lines_ignored = py_db.filename_to_lines_where_exceptions_are_ignored[ filename] = {} lines_ignored[int(line_number)] = 1 else: sys.stderr.write('pydev debugger: warning: trying to ignore exception thrown'\ ' on file that does not exist: %s (will have no effect)\n' % (filename,)) elif cmd_id == CMD_ENABLE_DONT_TRACE: if text: true_str = 'true' # Not all 3.x versions support u'str', so, doing workaround. if not IS_PY3K: true_str = unicode(true_str) mode = text.strip() == true_str pydevd_dont_trace.trace_filter(mode) 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 handle_exception(self, frame, event, arg): try: # print 'handle_exception', frame.f_lineno, frame.f_code.co_name # We have 3 things in arg: exception type, description, traceback object trace_obj = arg[2] main_debugger = self._args[0] if not hasattr(trace_obj, 'tb_next'): return #Not always there on Jython... initial_trace_obj = trace_obj if trace_obj.tb_next is None and trace_obj.tb_frame is frame: #I.e.: tb_next should be only None in the context it was thrown (trace_obj.tb_frame is frame is just a double check). if main_debugger.break_on_exceptions_thrown_in_same_context: #Option: Don't break if an exception is caught in the same function from which it is thrown return else: #Get the trace_obj from where the exception was raised... while trace_obj.tb_next is not None: trace_obj = trace_obj.tb_next if main_debugger.ignore_exceptions_thrown_in_lines_with_ignore_exception: for check_trace_obj in (initial_trace_obj, trace_obj): filename = get_abs_path_real_path_and_base_from_frame( check_trace_obj.tb_frame)[1] filename_to_lines_where_exceptions_are_ignored = self.filename_to_lines_where_exceptions_are_ignored lines_ignored = filename_to_lines_where_exceptions_are_ignored.get( filename) if lines_ignored is None: lines_ignored = filename_to_lines_where_exceptions_are_ignored[ filename] = {} try: curr_stat = os.stat(filename) curr_stat = (curr_stat.st_size, curr_stat.st_mtime) except: curr_stat = None last_stat = self.filename_to_stat_info.get(filename) if last_stat != curr_stat: self.filename_to_stat_info[filename] = curr_stat lines_ignored.clear() try: linecache.checkcache(filename) except: #Jython 2.1 linecache.checkcache() from_user_input = main_debugger.filename_to_lines_where_exceptions_are_ignored.get( filename) if from_user_input: merged = {} merged.update(lines_ignored) #Override what we have with the related entries that the user entered merged.update(from_user_input) else: merged = lines_ignored exc_lineno = check_trace_obj.tb_lineno # print ('lines ignored', lines_ignored) # print ('user input', from_user_input) # print ('merged', merged, 'curr', exc_lineno) if not dict_contains( merged, exc_lineno ): #Note: check on merged but update lines_ignored. try: line = linecache.getline( filename, exc_lineno, check_trace_obj.tb_frame.f_globals) except: #Jython 2.1 line = linecache.getline(filename, exc_lineno) if IGNORE_EXCEPTION_TAG.match(line) is not None: lines_ignored[exc_lineno] = 1 return else: #Put in the cache saying not to ignore lines_ignored[exc_lineno] = 0 else: #Ok, dict has it already cached, so, let's check it... if merged.get(exc_lineno, 0): return thread = self._args[3] try: frame_id_to_frame = {} frame_id_to_frame[id(frame)] = frame f = trace_obj.tb_frame while f is not None: frame_id_to_frame[id(f)] = f f = f.f_back f = None thread_id = get_thread_id(thread) pydevd_vars.add_additional_frame_by_id(thread_id, frame_id_to_frame) try: main_debugger.send_caught_exception_stack( thread, arg, id(frame)) self.set_suspend(thread, CMD_STEP_CAUGHT_EXCEPTION) self.do_wait_suspend(thread, frame, event, arg) main_debugger.send_caught_exception_stack_proceeded(thread) finally: pydevd_vars.remove_additional_frame_by_id(thread_id) except: traceback.print_exc() main_debugger.set_trace_for_frame_and_parents(frame) finally: #Clear some local variables... trace_obj = None initial_trace_obj = None check_trace_obj = None f = None frame_id_to_frame = None main_debugger = None thread = None
def error_once(message): if not dict_contains(WARN_ONCE_MAP, message): WARN_ONCE_MAP[message] = True error(message)
def _is_jinja2_internal_function(frame): return dict_contains(frame.f_locals, 'self') and frame.f_locals['self'].__class__.__name__ in \ ('LoopContext', 'TemplateReference', 'Macro', 'BlockReference')
def _is_jinja2_context_call(frame): return dict_contains(frame.f_locals, "_Context__obj")
def find_frame(thread_id, frame_id): """ returns a frame on the thread that has a given frame_id """ try: curr_thread_id = get_thread_id(threading.currentThread()) if thread_id != curr_thread_id: try: return get_custom_frame(thread_id, frame_id) # I.e.: thread_id could be a stackless frame id + thread_id. except: pass raise VariableError("find_frame: must execute on same thread (%s != %s)" % (thread_id, curr_thread_id)) lookingFor = int(frame_id) if AdditionalFramesContainer.additional_frames: if dict_contains(AdditionalFramesContainer.additional_frames, thread_id): frame = AdditionalFramesContainer.additional_frames[thread_id].get(lookingFor) if frame is not None: return frame curFrame = get_frame() if frame_id == "*": return curFrame # any frame is specified with "*" frameFound = None for frame in _iter_frames(curFrame): if lookingFor == id(frame): frameFound = frame del frame break del frame # Important: python can hold a reference to the frame from the current context # if an exception is raised, so, if we don't explicitly add those deletes # we might have those variables living much more than we'd want to. # I.e.: sys.exc_info holding reference to frame that raises exception (so, other places # need to call sys.exc_clear()) del curFrame if frameFound is None: msgFrames = '' i = 0 for frame in _iter_frames(get_frame()): i += 1 msgFrames += str(id(frame)) if i % 5 == 0: msgFrames += '\n' else: msgFrames += ' - ' errMsg = '''find_frame: frame not found. Looking for thread_id:%s, frame_id:%s Current thread_id:%s, available frames: %s\n ''' % (thread_id, lookingFor, curr_thread_id, msgFrames) sys.stderr.write(errMsg) return None return frameFound except: import traceback traceback.print_exc() return None
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 trace_dispatch(self, frame, event, arg): # ENDIF main_debugger, filename, info, thread = self._args try: # print 'frame trace_dispatch', frame.f_lineno, frame.f_code.co_name, event info.is_tracing = True if main_debugger._finish_debugging_session: return None if event == "call" and main_debugger.signature_factory: send_signature_call_trace(main_debugger, frame, filename) plugin_manager = main_debugger.plugin is_exception_event = event == "exception" has_exception_breakpoints = ( main_debugger.break_on_caught_exceptions or main_debugger.has_plugin_exception_breaks ) if is_exception_event: if has_exception_breakpoints: flag, frame = self.should_stop_on_exception(frame, event, arg) if flag: self.handle_exception(frame, event, arg) return self.trace_dispatch elif event not in ("line", "call", "return"): # I believe this can only happen in jython on some frontiers on jython and java code, which we don't want to trace. return None stop_frame = info.pydev_step_stop step_cmd = info.pydev_step_cmd if is_exception_event: breakpoints_for_file = None if ( stop_frame and stop_frame is not frame and step_cmd == CMD_STEP_OVER and arg[0] in (StopIteration, GeneratorExit) and arg[2] is None ): info.pydev_step_cmd = CMD_STEP_INTO info.pydev_step_stop = None else: # If we are in single step mode and something causes us to exit the current frame, we need to make sure we break # eventually. Force the step mode to step into and the step stop frame to None. # I.e.: F6 in the end of a function should stop in the next possible position (instead of forcing the user # to make a step in or step over at that location). # Note: this is especially troublesome when we're skipping code with the # @DontTrace comment. if stop_frame is frame and event == "return" and step_cmd in (CMD_STEP_RETURN, CMD_STEP_OVER): if not frame.f_code.co_flags & CO_GENERATOR: info.pydev_step_cmd = CMD_STEP_INTO info.pydev_step_stop = None breakpoints_for_file = main_debugger.breakpoints.get(filename) can_skip = False if info.pydev_state == STATE_RUN: # we can skip if: # - we have no stop marked # - we should make a step return/step over and we're not in the current frame can_skip = (step_cmd == -1 and stop_frame is None) or ( step_cmd in (CMD_STEP_RETURN, CMD_STEP_OVER) and stop_frame is not frame ) if can_skip and plugin_manager is not None and main_debugger.has_plugin_line_breaks: can_skip = not plugin_manager.can_not_skip(main_debugger, self, frame) if can_skip and main_debugger.show_return_values: # trace function for showing return values after step over if ( info.pydev_step_cmd == CMD_STEP_OVER and hasattr(frame, "f_back") and frame.f_back == info.pydev_step_stop ): can_skip = False # Let's check to see if we are in a function that has a breakpoint. If we don't have a breakpoint, # we will return nothing for the next trace # also, after we hit a breakpoint and go to some other debugging state, we have to force the set trace anyway, # so, that's why the additional checks are there. if not breakpoints_for_file: if can_skip: if has_exception_breakpoints: return self.trace_exception else: return None else: # checks the breakpoint to see if there is a context match in some function curr_func_name = frame.f_code.co_name # global context is set with an empty name if curr_func_name in ("?", "<module>"): curr_func_name = "" for breakpoint in dict_iter_values(breakpoints_for_file): # jython does not support itervalues() # will match either global or some function if breakpoint.func_name in ("None", curr_func_name): break else: # if we had some break, it won't get here (so, that's a context that we want to skip) if can_skip: if has_exception_breakpoints: return self.trace_exception else: return None # We may have hit a breakpoint or we are already in step mode. Either way, let's check what we should do in this frame # print 'NOT skipped', frame.f_lineno, frame.f_code.co_name, event try: line = frame.f_lineno flag = False # return is not taken into account for breakpoint hit because we'd have a double-hit in this case # (one for the line and the other for the return). stop_info = {} breakpoint = None exist_result = False stop = False bp_type = None if ( not flag and event != "return" and info.pydev_state != STATE_SUSPEND and breakpoints_for_file is not None and dict_contains(breakpoints_for_file, line) ): breakpoint = breakpoints_for_file[line] new_frame = frame stop = True if step_cmd == CMD_STEP_OVER and stop_frame is frame and event in ("line", "return"): stop = ( False ) # we don't stop on breakpoint if we have to stop by step-over (it will be processed later) elif plugin_manager is not None and main_debugger.has_plugin_line_breaks: result = plugin_manager.get_breakpoint(main_debugger, self, frame, event, self._args) if result: exist_result = True (flag, breakpoint, new_frame, bp_type) = result if breakpoint: # ok, hit breakpoint, now, we have to discover if it is a conditional breakpoint # lets do the conditional stuff here if stop or exist_result: condition = breakpoint.condition if condition is not None: try: val = eval(condition, new_frame.f_globals, new_frame.f_locals) if not val: return self.trace_dispatch except: if type(condition) != type(""): if hasattr(condition, "encode"): condition = condition.encode("utf-8") msg = "Error while evaluating expression: %s\n" % (condition,) sys.stderr.write(msg) traceback.print_exc() if not main_debugger.suspend_on_breakpoint_exception: return self.trace_dispatch else: stop = True try: # add exception_type and stacktrace into thread additional info etype, value, tb = sys.exc_info() try: error = "".join(traceback.format_exception_only(etype, value)) stack = traceback.extract_stack(f=tb.tb_frame.f_back) # On self.set_suspend(thread, CMD_SET_BREAK) this info will be # sent to the client. info.conditional_breakpoint_exception = ( "Condition:\n" + condition + "\n\nError:\n" + error, stack, ) finally: etype, value, tb = None, None, None except: traceback.print_exc() if breakpoint.expression is not None: try: try: val = eval(breakpoint.expression, new_frame.f_globals, new_frame.f_locals) except: val = sys.exc_info()[1] finally: if val is not None: info.pydev_message = str(val) if not main_debugger.first_breakpoint_reached: if event == "call": if hasattr(frame, "f_back"): back = frame.f_back if back is not None: # When we start debug session, we call execfile in pydevd run function. It produces an additional # 'call' event for tracing and we stop on the first line of code twice. _, back_filename, base = get_abs_path_real_path_and_base_from_frame(back) if (base == DEBUG_START[0] and back.f_code.co_name == DEBUG_START[1]) or ( base == DEBUG_START_PY3K[0] and back.f_code.co_name == DEBUG_START_PY3K[1] ): stop = False main_debugger.first_breakpoint_reached = True else: # if the frame is traced after breakpoint stop, # but the file should be ignored while stepping because of filters if step_cmd != -1: if main_debugger.is_filter_enabled and main_debugger.is_ignored_by_filters(filename): # ignore files matching stepping filters return self.trace_dispatch if main_debugger.is_filter_libraries and main_debugger.not_in_scope(filename): # ignore library files while stepping return self.trace_dispatch if main_debugger.show_return_values or main_debugger.remove_return_values_flag: self.manage_return_values(main_debugger, frame, event, arg) if stop: self.set_suspend(thread, CMD_SET_BREAK) if breakpoint and breakpoint.suspend_policy == "ALL": main_debugger.suspend_all_other_threads(thread) elif flag and plugin_manager is not None: result = plugin_manager.suspend(main_debugger, thread, frame, bp_type) if result: frame = result # if thread has a suspend flag, we suspend with a busy wait if info.pydev_state == STATE_SUSPEND: self.do_wait_suspend(thread, frame, event, arg) return self.trace_dispatch except: traceback.print_exc() raise # step handling. We stop when we hit the right frame try: should_skip = 0 if pydevd_dont_trace.should_trace_hook is not None: if self.should_skip == -1: # I.e.: cache the result on self.should_skip (no need to evaluate the same frame multiple times). # Note that on a code reload, we won't re-evaluate this because in practice, the frame.f_code # Which will be handled by this frame is read-only, so, we can cache it safely. if not pydevd_dont_trace.should_trace_hook(frame, filename): # -1, 0, 1 to be Cython-friendly should_skip = self.should_skip = 1 else: should_skip = self.should_skip = 0 else: should_skip = self.should_skip plugin_stop = False if should_skip: stop = False elif step_cmd == CMD_STEP_INTO: stop = event in ("line", "return") if plugin_manager is not None: result = plugin_manager.cmd_step_into(main_debugger, frame, event, self._args, stop_info, stop) if result: stop, plugin_stop = result elif step_cmd == CMD_STEP_INTO_MY_CODE: if not main_debugger.not_in_scope(frame.f_code.co_filename): stop = event == "line" elif step_cmd == CMD_STEP_OVER: stop = stop_frame is frame and event in ("line", "return") if frame.f_code.co_flags & CO_GENERATOR: if event == "return": stop = False if plugin_manager is not None: result = plugin_manager.cmd_step_over(main_debugger, frame, event, self._args, stop_info, stop) if result: stop, plugin_stop = result elif step_cmd == CMD_SMART_STEP_INTO: stop = False if info.pydev_smart_step_stop is frame: info.pydev_func_name = ".invalid." # Must match the type in cython info.pydev_smart_step_stop = None if event == "line" or event == "exception": curr_func_name = frame.f_code.co_name # global context is set with an empty name if curr_func_name in ("?", "<module>") or curr_func_name is None: curr_func_name = "" if curr_func_name == info.pydev_func_name: stop = True elif step_cmd == CMD_STEP_RETURN: stop = event == "return" and stop_frame is frame elif step_cmd == CMD_RUN_TO_LINE or step_cmd == CMD_SET_NEXT_STATEMENT: stop = False if event == "line" or event == "exception": # Yes, we can only act on line events (weird hum?) # Note: This code is duplicated at pydevd.py # Acting on exception events after debugger breaks with exception curr_func_name = frame.f_code.co_name # global context is set with an empty name if curr_func_name in ("?", "<module>"): curr_func_name = "" if curr_func_name == info.pydev_func_name: line = info.pydev_next_line if frame.f_lineno == line: stop = True else: if frame.f_trace is None: frame.f_trace = self.trace_dispatch frame.f_lineno = line frame.f_trace = None stop = True else: stop = False if stop and step_cmd != -1 and IS_PY3K: # in Py3k we start script via our custom `execfile` function, and we shouldn't stop there # while stepping when execution is finished if event == "return" and hasattr(frame, "f_back") and hasattr(frame.f_back, "f_code"): back_filename = os.path.basename(frame.f_back.f_code.co_filename) file_type = get_file_type(back_filename) if file_type == PYDEV_FILE: stop = False if plugin_stop: stopped_on_plugin = plugin_manager.stop( main_debugger, frame, event, self._args, stop_info, arg, step_cmd ) elif stop: if event == "line": self.set_suspend(thread, step_cmd) self.do_wait_suspend(thread, frame, event, arg) else: # return event back = frame.f_back if back is not None: # When we get to the pydevd run function, the debugging has actually finished for the main thread # (note that it can still go on for other threads, but for this one, we just make it finish) # So, just setting it to None should be OK _, back_filename, base = get_abs_path_real_path_and_base_from_frame(back) if base == DEBUG_START[0] and back.f_code.co_name == DEBUG_START[1]: back = None elif base == TRACE_PROPERTY: # We dont want to trace the return event of pydevd_traceproperty (custom property for debugging) # if we're in a return, we want it to appear to the user in the previous frame! return None elif pydevd_dont_trace.should_trace_hook is not None: if not pydevd_dont_trace.should_trace_hook(back, back_filename): # In this case, we'll have to skip the previous one because it shouldn't be traced. # Also, we have to reset the tracing, because if the parent's parent (or some # other parent) has to be traced and it's not currently, we wouldn't stop where # we should anymore (so, a step in/over/return may not stop anywhere if no parent is traced). # Related test: _debugger_case17a.py main_debugger.set_trace_for_frame_and_parents(back, overwrite_prev_trace=True) return None if back is not None: # if we're in a return, we want it to appear to the user in the previous frame! self.set_suspend(thread, step_cmd) self.do_wait_suspend(thread, back, event, arg) else: # in jython we may not have a back frame info.pydev_step_stop = None info.pydev_step_cmd = -1 info.pydev_state = STATE_RUN except KeyboardInterrupt: raise except: try: traceback.print_exc() info.pydev_step_cmd = -1 except: return None # if we are quitting, let's stop the tracing retVal = None if not main_debugger.quitting: retVal = self.trace_dispatch return retVal finally: info.is_tracing = False
def get_referrer_info(searched_obj): DEBUG = 0 if DEBUG: sys.stderr.write('Getting referrers info.\n') try: try: if searched_obj is None: ret = ['<xml>\n'] ret.append('<for>\n') ret.append(pydevd_xml.var_to_xml( searched_obj, 'Skipping getting referrers for None', additionalInXml=' id="%s"' % (id(searched_obj),))) ret.append('</for>\n') ret.append('</xml>') ret = ''.join(ret) return ret obj_id = id(searched_obj) try: if DEBUG: sys.stderr.write('Getting referrers...\n') import gc referrers = gc.get_referrers(searched_obj) except: traceback.print_exc() ret = ['<xml>\n'] ret.append('<for>\n') ret.append(pydevd_xml.var_to_xml( searched_obj, 'Exception raised while trying to get_referrers.', additionalInXml=' id="%s"' % (id(searched_obj),))) ret.append('</for>\n') ret.append('</xml>') ret = ''.join(ret) return ret if DEBUG: sys.stderr.write('Found %s referrers.\n' % (len(referrers),)) curr_frame = sys._getframe() frame_type = type(curr_frame) #Ignore this frame and any caller frame of this frame ignore_frames = {} #Should be a set, but it's not available on all python versions. while curr_frame is not None: if basename(curr_frame.f_code.co_filename).startswith('pydev'): ignore_frames[curr_frame] = 1 curr_frame = curr_frame.f_back ret = ['<xml>\n'] ret.append('<for>\n') if DEBUG: sys.stderr.write('Searching Referrers of obj with id="%s"\n' % (obj_id,)) ret.append(pydevd_xml.var_to_xml( searched_obj, 'Referrers of obj with id="%s"' % (obj_id,))) ret.append('</for>\n') all_objects = None for r in referrers: try: if dict_contains(ignore_frames, r): continue #Skip the references we may add ourselves except: pass #Ok: unhashable type checked... if r is referrers: continue r_type = type(r) r_id = str(id(r)) representation = str(r_type) found_as = '' if r_type == frame_type: if DEBUG: sys.stderr.write('Found frame referrer: %r\n' % (r,)) for key, val in r.f_locals.items(): if val is searched_obj: found_as = key break elif r_type == dict: if DEBUG: sys.stderr.write('Found dict referrer: %r\n' % (r,)) # Try to check if it's a value in the dict (and under which key it was found) for key, val in r.items(): if val is searched_obj: found_as = key if DEBUG: sys.stderr.write(' Found as %r in dict\n' % (found_as,)) break #Ok, there's one annoying thing: many times we find it in a dict from an instance, #but with this we don't directly have the class, only the dict, so, to workaround that #we iterate over all reachable objects ad check if one of those has the given dict. if all_objects is None: all_objects = gc.get_objects() for x in all_objects: try: if getattr(x, '__dict__', None) is r: r = x r_type = type(x) r_id = str(id(r)) representation = str(r_type) break except: pass #Just ignore any error here (i.e.: ReferenceError, etc.) elif r_type in (tuple, list): if DEBUG: sys.stderr.write('Found tuple referrer: %r\n' % (r,)) #Don't use enumerate() because not all Python versions have it. i = 0 for x in r: if x is searched_obj: found_as = '%s[%s]' % (r_type.__name__, i) if DEBUG: sys.stderr.write(' Found as %s in tuple: \n' % (found_as,)) break i += 1 if found_as: if not isinstance(found_as, str): found_as = str(found_as) found_as = ' found_as="%s"' % (pydevd_xml.make_valid_xml_value(found_as),) ret.append(pydevd_xml.var_to_xml( r, representation, additionalInXml=' id="%s"%s' % (r_id, found_as))) finally: if DEBUG: sys.stderr.write('Done searching for references.\n') #If we have any exceptions, don't keep dangling references from this frame to any of our objects. all_objects = None referrers = None searched_obj = None r = None x = None key = None val = None curr_frame = None ignore_frames = None except: traceback.print_exc() ret = ['<xml>\n'] ret.append('<for>\n') ret.append(pydevd_xml.var_to_xml( searched_obj, 'Error getting referrers for:', additionalInXml=' id="%s"' % (id(searched_obj),))) ret.append('</for>\n') ret.append('</xml>') ret = ''.join(ret) return ret ret.append('</xml>') ret = ''.join(ret) return ret
def find_frame(thread_id, frame_id): """ returns a frame on the thread that has a given frame_id """ try: curr_thread_id = get_thread_id(threading.currentThread()) if thread_id != curr_thread_id: try: return get_custom_frame( thread_id, frame_id ) # I.e.: thread_id could be a stackless frame id + thread_id. except: pass raise VariableError( "find_frame: must execute on same thread (%s != %s)" % (thread_id, curr_thread_id)) lookingFor = int(frame_id) if AdditionalFramesContainer.additional_frames: if dict_contains(AdditionalFramesContainer.additional_frames, thread_id): frame = AdditionalFramesContainer.additional_frames[ thread_id].get(lookingFor) if frame is not None: return frame curFrame = get_frame() if frame_id == "*": return curFrame # any frame is specified with "*" frameFound = None for frame in _iter_frames(curFrame): if lookingFor == id(frame): frameFound = frame del frame break del frame # Important: python can hold a reference to the frame from the current context # if an exception is raised, so, if we don't explicitly add those deletes # we might have those variables living much more than we'd want to. # I.e.: sys.exc_info holding reference to frame that raises exception (so, other places # need to call sys.exc_clear()) del curFrame if frameFound is None: msgFrames = '' i = 0 for frame in _iter_frames(get_frame()): i += 1 msgFrames += str(id(frame)) if i % 5 == 0: msgFrames += '\n' else: msgFrames += ' - ' errMsg = '''find_frame: frame not found. Looking for thread_id:%s, frame_id:%s Current thread_id:%s, available frames: %s\n ''' % (thread_id, lookingFor, curr_thread_id, msgFrames) sys.stderr.write(errMsg) return None return frameFound except: import traceback traceback.print_exc() return None
def trace_dispatch(self, frame, event, arg): # ENDIF main_debugger, filename, info, thread, frame_skips_cache, frame_cache_key = self._args # print('frame trace_dispatch', frame.f_lineno, frame.f_code.co_name, event, info.pydev_step_cmd) try: info.is_tracing = True line = frame.f_lineno line_cache_key = (frame_cache_key, line) if main_debugger._finish_debugging_session: return None plugin_manager = main_debugger.plugin is_exception_event = event == 'exception' has_exception_breakpoints = main_debugger.break_on_caught_exceptions or main_debugger.has_plugin_exception_breaks if is_exception_event: if has_exception_breakpoints: flag, frame = self.should_stop_on_exception( frame, event, arg) if flag: self.handle_exception(frame, event, arg) return self.trace_dispatch is_line = False is_return = False is_call = False else: is_line = event == 'line' is_return = event == 'return' is_call = event == 'call' if not is_line and not is_return and not is_call: # I believe this can only happen in jython on some frontiers on jython and java code, which we don't want to trace. return None need_trace_return = False if is_call and main_debugger.signature_factory: need_trace_return = send_signature_call_trace( main_debugger, frame, filename) if is_return and main_debugger.signature_factory: send_signature_return_trace(main_debugger, frame, filename, arg) stop_frame = info.pydev_step_stop step_cmd = info.pydev_step_cmd if is_exception_event: breakpoints_for_file = None # CMD_STEP_OVER = 108 if stop_frame and stop_frame is not frame and step_cmd == 108 and \ arg[0] in (StopIteration, GeneratorExit) and arg[2] is None: info.pydev_step_cmd = 107 # CMD_STEP_INTO = 107 info.pydev_step_stop = None else: # If we are in single step mode and something causes us to exit the current frame, we need to make sure we break # eventually. Force the step mode to step into and the step stop frame to None. # I.e.: F6 in the end of a function should stop in the next possible position (instead of forcing the user # to make a step in or step over at that location). # Note: this is especially troublesome when we're skipping code with the # @DontTrace comment. if stop_frame is frame and is_return and step_cmd in ( 109, 108): # CMD_STEP_RETURN = 109, CMD_STEP_OVER = 108 if not frame.f_code.co_flags & 0x20: # CO_GENERATOR = 0x20 (inspect.CO_GENERATOR) info.pydev_step_cmd = 107 # CMD_STEP_INTO = 107 info.pydev_step_stop = None breakpoints_for_file = main_debugger.breakpoints.get(filename) can_skip = False if info.pydev_state == 1: # STATE_RUN = 1 #we can skip if: #- we have no stop marked #- we should make a step return/step over and we're not in the current frame # CMD_STEP_RETURN = 109, CMD_STEP_OVER = 108 can_skip = (step_cmd == -1 and stop_frame is None) \ or (step_cmd in (109, 108) and stop_frame is not frame) if can_skip: if plugin_manager is not None and main_debugger.has_plugin_line_breaks: can_skip = not plugin_manager.can_not_skip( main_debugger, self, frame) # CMD_STEP_OVER = 108 if can_skip and is_return and main_debugger.show_return_values and info.pydev_step_cmd == 108 and frame.f_back is info.pydev_step_stop: # trace function for showing return values after step over can_skip = False if main_debugger.frame_eval_func and event == 'return' and info.pydev_step_cmd == -1: frames_set = main_debugger.disable_tracing_after_exit_frames.get( get_thread_id(thread), None) if frames_set is not None: if frame in frames_set: frames_set.remove(frame) if len(frames_set) == 0: # there were some frames, but we exited all of them, stop tracing main_debugger.disable_tracing_after_exit_frames.pop( get_thread_id(thread)) main_debugger.SetTrace(None) # Let's check to see if we are in a function that has a breakpoint. If we don't have a breakpoint, # we will return nothing for the next trace # also, after we hit a breakpoint and go to some other debugging state, we have to force the set trace anyway, # so, that's why the additional checks are there. if not breakpoints_for_file: if can_skip: if has_exception_breakpoints: return self.trace_exception else: if need_trace_return: return self.trace_return else: return None else: # When cached, 0 means we don't have a breakpoint and 1 means we have. if can_skip: breakpoints_in_line_cache = frame_skips_cache.get( line_cache_key, -1) if breakpoints_in_line_cache == 0: return self.trace_dispatch breakpoints_in_frame_cache = frame_skips_cache.get( frame_cache_key, -1) if breakpoints_in_frame_cache != -1: # Gotten from cache. has_breakpoint_in_frame = breakpoints_in_frame_cache == 1 else: has_breakpoint_in_frame = False # Checks the breakpoint to see if there is a context match in some function curr_func_name = frame.f_code.co_name #global context is set with an empty name if curr_func_name in ('?', '<module>'): curr_func_name = '' for breakpoint in dict_iter_values( breakpoints_for_file ): #jython does not support itervalues() #will match either global or some function if breakpoint.func_name in ('None', curr_func_name): has_breakpoint_in_frame = True break # Cache the value (1 or 0 or -1 for default because of cython). if has_breakpoint_in_frame: frame_skips_cache[frame_cache_key] = 1 else: frame_skips_cache[frame_cache_key] = 0 if can_skip and not has_breakpoint_in_frame: if has_exception_breakpoints: return self.trace_exception else: if need_trace_return: return self.trace_return else: return None #We may have hit a breakpoint or we are already in step mode. Either way, let's check what we should do in this frame #print('NOT skipped', frame.f_lineno, frame.f_code.co_name, event) try: flag = False #return is not taken into account for breakpoint hit because we'd have a double-hit in this case #(one for the line and the other for the return). stop_info = {} breakpoint = None exist_result = False stop = False bp_type = None if not is_return and info.pydev_state != STATE_SUSPEND and breakpoints_for_file is not None and dict_contains( breakpoints_for_file, line): breakpoint = breakpoints_for_file[line] new_frame = frame stop = True if step_cmd == CMD_STEP_OVER and stop_frame is frame and ( is_line or is_return): stop = False #we don't stop on breakpoint if we have to stop by step-over (it will be processed later) elif plugin_manager is not None and main_debugger.has_plugin_line_breaks: result = plugin_manager.get_breakpoint( main_debugger, self, frame, event, self._args) if result: exist_result = True flag, breakpoint, new_frame, bp_type = result if breakpoint: #ok, hit breakpoint, now, we have to discover if it is a conditional breakpoint # lets do the conditional stuff here if stop or exist_result: condition = breakpoint.condition if condition is not None: try: val = eval(condition, new_frame.f_globals, new_frame.f_locals) if not val: return self.trace_dispatch except: if type(condition) != type(''): if hasattr(condition, 'encode'): condition = condition.encode('utf-8') msg = 'Error while evaluating expression: %s\n' % ( condition, ) sys.stderr.write(msg) traceback.print_exc() if not main_debugger.suspend_on_breakpoint_exception: return self.trace_dispatch else: stop = True try: # add exception_type and stacktrace into thread additional info etype, value, tb = sys.exc_info() try: error = ''.join( traceback. format_exception_only( etype, value)) stack = traceback.extract_stack( f=tb.tb_frame.f_back) # On self.set_suspend(thread, CMD_SET_BREAK) this info will be # sent to the client. info.conditional_breakpoint_exception = \ ('Condition:\n' + condition + '\n\nError:\n' + error, stack) finally: etype, value, tb = None, None, None except: traceback.print_exc() if breakpoint.expression is not None: try: try: val = eval(breakpoint.expression, new_frame.f_globals, new_frame.f_locals) except: val = sys.exc_info()[1] finally: if val is not None: info.pydev_message = str(val) if not main_debugger.first_breakpoint_reached: if is_call: back = frame.f_back if back is not None: # When we start debug session, we call execfile in pydevd run function. It produces an additional # 'call' event for tracing and we stop on the first line of code twice. _, back_filename, base = get_abs_path_real_path_and_base_from_frame( back) if (base == DEBUG_START[0] and back.f_code.co_name == DEBUG_START[1]) or \ (base == DEBUG_START_PY3K[0] and back.f_code.co_name == DEBUG_START_PY3K[1]): stop = False main_debugger.first_breakpoint_reached = True else: # if the frame is traced after breakpoint stop, # but the file should be ignored while stepping because of filters if step_cmd != -1: if main_debugger.is_filter_enabled and main_debugger.is_ignored_by_filters( filename): # ignore files matching stepping filters return self.trace_dispatch if main_debugger.is_filter_libraries and main_debugger.not_in_scope( filename): # ignore library files while stepping return self.trace_dispatch if main_debugger.show_return_values or main_debugger.remove_return_values_flag: self.manage_return_values(main_debugger, frame, event, arg) if stop: self.set_suspend(thread, CMD_SET_BREAK) if breakpoint and breakpoint.suspend_policy == "ALL": main_debugger.suspend_all_other_threads(thread) elif flag and plugin_manager is not None: result = plugin_manager.suspend(main_debugger, thread, frame, bp_type) if result: frame = result # if thread has a suspend flag, we suspend with a busy wait if info.pydev_state == STATE_SUSPEND: self.do_wait_suspend(thread, frame, event, arg) return self.trace_dispatch else: if not breakpoint and not is_return: # No stop from anyone and no breakpoint found in line (cache that). frame_skips_cache[line_cache_key] = 0 except: traceback.print_exc() raise #step handling. We stop when we hit the right frame try: should_skip = 0 if pydevd_dont_trace.should_trace_hook is not None: if self.should_skip == -1: # I.e.: cache the result on self.should_skip (no need to evaluate the same frame multiple times). # Note that on a code reload, we won't re-evaluate this because in practice, the frame.f_code # Which will be handled by this frame is read-only, so, we can cache it safely. if not pydevd_dont_trace.should_trace_hook( frame, filename): # -1, 0, 1 to be Cython-friendly should_skip = self.should_skip = 1 else: should_skip = self.should_skip = 0 else: should_skip = self.should_skip plugin_stop = False if should_skip: stop = False elif step_cmd == CMD_STEP_INTO: stop = is_line or is_return if plugin_manager is not None: result = plugin_manager.cmd_step_into( main_debugger, frame, event, self._args, stop_info, stop) if result: stop, plugin_stop = result elif step_cmd == CMD_STEP_INTO_MY_CODE: if not main_debugger.not_in_scope( frame.f_code.co_filename): stop = is_line elif step_cmd == CMD_STEP_OVER: stop = stop_frame is frame and (is_line or is_return) if frame.f_code.co_flags & CO_GENERATOR: if is_return: stop = False if plugin_manager is not None: result = plugin_manager.cmd_step_over( main_debugger, frame, event, self._args, stop_info, stop) if result: stop, plugin_stop = result elif step_cmd == CMD_SMART_STEP_INTO: stop = False if info.pydev_smart_step_stop is frame: info.pydev_func_name = '.invalid.' # Must match the type in cython info.pydev_smart_step_stop = None if is_line or is_exception_event: curr_func_name = frame.f_code.co_name #global context is set with an empty name if curr_func_name in ( '?', '<module>') or curr_func_name is None: curr_func_name = '' if curr_func_name == info.pydev_func_name: stop = True elif step_cmd == CMD_STEP_RETURN: stop = is_return and stop_frame is frame elif step_cmd == CMD_RUN_TO_LINE or step_cmd == CMD_SET_NEXT_STATEMENT: stop = False if is_line or is_exception_event: #Yes, we can only act on line events (weird hum?) #Note: This code is duplicated at pydevd.py #Acting on exception events after debugger breaks with exception curr_func_name = frame.f_code.co_name #global context is set with an empty name if curr_func_name in ('?', '<module>'): curr_func_name = '' if curr_func_name == info.pydev_func_name: line = info.pydev_next_line if frame.f_lineno == line: stop = True else: if frame.f_trace is None: frame.f_trace = self.trace_dispatch frame.f_lineno = line frame.f_trace = None stop = True else: stop = False if step_cmd != -1 and is_return and IS_PY3K and hasattr( frame, "f_back"): f_code = getattr(frame.f_back, 'f_code', None) if f_code is not None: back_filename = os.path.basename(f_code.co_filename) file_type = get_file_type(back_filename) if file_type == PYDEV_FILE: stop = False if plugin_stop: stopped_on_plugin = plugin_manager.stop( main_debugger, frame, event, self._args, stop_info, arg, step_cmd) elif stop: if is_line: self.set_suspend(thread, step_cmd) self.do_wait_suspend(thread, frame, event, arg) else: #return event back = frame.f_back if back is not None: #When we get to the pydevd run function, the debugging has actually finished for the main thread #(note that it can still go on for other threads, but for this one, we just make it finish) #So, just setting it to None should be OK _, back_filename, base = get_abs_path_real_path_and_base_from_frame( back) if base == DEBUG_START[ 0] and back.f_code.co_name == DEBUG_START[ 1]: back = None elif base == TRACE_PROPERTY: # We dont want to trace the return event of pydevd_traceproperty (custom property for debugging) #if we're in a return, we want it to appear to the user in the previous frame! return None elif pydevd_dont_trace.should_trace_hook is not None: if not pydevd_dont_trace.should_trace_hook( back, back_filename): # In this case, we'll have to skip the previous one because it shouldn't be traced. # Also, we have to reset the tracing, because if the parent's parent (or some # other parent) has to be traced and it's not currently, we wouldn't stop where # we should anymore (so, a step in/over/return may not stop anywhere if no parent is traced). # Related test: _debugger_case17a.py main_debugger.set_trace_for_frame_and_parents( back, overwrite_prev_trace=True) return None if back is not None: #if we're in a return, we want it to appear to the user in the previous frame! self.set_suspend(thread, step_cmd) self.do_wait_suspend(thread, back, event, arg) else: #in jython we may not have a back frame info.pydev_step_stop = None info.pydev_step_cmd = -1 info.pydev_state = STATE_RUN except KeyboardInterrupt: raise except: try: traceback.print_exc() info.pydev_step_cmd = -1 except: return None #if we are quitting, let's stop the tracing retVal = None if not main_debugger.quitting: retVal = self.trace_dispatch return retVal finally: info.is_tracing = False
def log_event(self, frame): event_time = cur_time() - self.start_time # Debug loop iterations # if isinstance(self_obj, asyncio.base_events.BaseEventLoop): # if method_name == "_run_once": # print("Loop iteration") if not hasattr(frame, "f_back") or frame.f_back is None: return back = frame.f_back if dict_contains(frame.f_locals, "self"): self_obj = frame.f_locals["self"] if isinstance(self_obj, asyncio.Task): method_name = frame.f_code.co_name if method_name == "set_result": task_id = id(self_obj) task_name = self.task_mgr.get(str(task_id)) send_message("asyncio_event", event_time, task_name, task_name, "thread", "stop", frame.f_code.co_filename, frame.f_lineno, frame) method_name = back.f_code.co_name if method_name == "__init__": task_id = id(self_obj) task_name = self.task_mgr.get(str(task_id)) send_message("asyncio_event", event_time, task_name, task_name, "thread", "start", frame.f_code.co_filename, frame.f_lineno, frame) method_name = frame.f_code.co_name if isinstance(self_obj, asyncio.Lock): if method_name in ("acquire", "release"): task_id = self.get_task_id(frame) task_name = self.task_mgr.get(str(task_id)) if method_name == "acquire": if not self_obj._waiters and not self_obj.locked(): send_message("asyncio_event", event_time, task_name, task_name, "lock", method_name + "_begin", frame.f_code.co_filename, frame.f_lineno, frame, lock_id=str(id(self_obj))) if self_obj.locked(): method_name += "_begin" else: method_name += "_end" elif method_name == "release": method_name += "_end" send_message("asyncio_event", event_time, task_name, task_name, "lock", method_name, frame.f_code.co_filename, frame.f_lineno, frame, lock_id=str(id(self_obj))) if isinstance(self_obj, asyncio.Queue): if method_name in ("put", "get", "_put", "_get"): task_id = self.get_task_id(frame) task_name = self.task_mgr.get(str(task_id)) if method_name == "put": send_message("asyncio_event", event_time, task_name, task_name, "lock", "acquire_begin", frame.f_code.co_filename, frame.f_lineno, frame, lock_id=str(id(self_obj))) elif method_name == "_put": send_message("asyncio_event", event_time, task_name, task_name, "lock", "acquire_end", frame.f_code.co_filename, frame.f_lineno, frame, lock_id=str(id(self_obj))) send_message("asyncio_event", event_time, task_name, task_name, "lock", "release", frame.f_code.co_filename, frame.f_lineno, frame, lock_id=str(id(self_obj))) elif method_name == "get": back = frame.f_back if back.f_code.co_name != "send": send_message("asyncio_event", event_time, task_name, task_name, "lock", "acquire_begin", frame.f_code.co_filename, frame.f_lineno, frame, lock_id=str(id(self_obj))) else: send_message("asyncio_event", event_time, task_name, task_name, "lock", "acquire_end", frame.f_code.co_filename, frame.f_lineno, frame, lock_id=str(id(self_obj))) send_message("asyncio_event", event_time, task_name, task_name, "lock", "release", frame.f_code.co_filename, frame.f_lineno, frame, lock_id=str(id(self_obj)))
def log_event(self, frame): write_log = False self_obj = None if dict_contains(frame.f_locals, "self"): self_obj = frame.f_locals["self"] if isinstance(self_obj, threading.Thread) or self_obj.__class__ == ObjectWrapper: write_log = True if hasattr(frame, "f_back") and frame.f_back is not None: back = frame.f_back if hasattr(back, "f_back") and back.f_back is not None: back = back.f_back if dict_contains(back.f_locals, "self"): if isinstance(back.f_locals["self"], threading.Thread): write_log = True try: if write_log: t = threadingCurrentThread() back = frame.f_back if not back: return _, name, back_base = pydevd_file_utils.get_abs_path_real_path_and_base_from_frame(back) event_time = cur_time() - self.start_time method_name = frame.f_code.co_name if isinstance(self_obj, threading.Thread): if not hasattr(self_obj, "_pydev_run_patched"): wrap_attr(self_obj, "run") if (method_name in THREAD_METHODS) and (back_base not in DONT_TRACE_THREADING or \ (method_name in INNER_METHODS and back_base in INNER_FILES)): thread_id = get_thread_id(self_obj) name = self_obj.getName() real_method = frame.f_code.co_name parent = None if real_method == "_stop": if back_base in INNER_FILES and \ back.f_code.co_name == "_wait_for_tstate_lock": back = back.f_back.f_back real_method = "stop" if hasattr(self_obj, "_pydev_join_called"): parent = get_thread_id(t) elif real_method == "join": # join called in the current thread, not in self object if not self_obj.is_alive(): return thread_id = get_thread_id(t) name = t.getName() setattr(self_obj, "_pydev_join_called", True) if real_method == "start": parent = get_thread_id(t) send_message("threading_event", event_time, name, thread_id, "thread", real_method, back.f_code.co_filename, back.f_lineno, back, parent=parent) # print(event_time, self_obj.getName(), thread_id, "thread", # real_method, back.f_code.co_filename, back.f_lineno) if method_name == "pydev_after_run_call": if hasattr(frame, "f_back") and frame.f_back is not None: back = frame.f_back if hasattr(back, "f_back") and back.f_back is not None: back = back.f_back if dict_contains(back.f_locals, "self"): if isinstance(back.f_locals["self"], threading.Thread): my_self_obj = frame.f_back.f_back.f_locals["self"] my_back = frame.f_back.f_back my_thread_id = get_thread_id(my_self_obj) send_massage = True if IS_PY3K and hasattr(my_self_obj, "_pydev_join_called"): send_massage = False # we can't detect stop after join in Python 2 yet if send_massage: send_message("threading_event", event_time, "Thread", my_thread_id, "thread", "stop", my_back.f_code.co_filename, my_back.f_lineno, my_back, parent=None) if self_obj.__class__ == ObjectWrapper: if back_base in DONT_TRACE_THREADING: # do not trace methods called from threading return back_back_base = pydevd_file_utils.get_abs_path_real_path_and_base_from_frame(back.f_back)[-1] back = back.f_back if back_back_base in DONT_TRACE_THREADING: # back_back_base is the file, where the method was called froms return if method_name == "__init__": send_message("threading_event", event_time, t.getName(), get_thread_id(t), "lock", method_name, back.f_code.co_filename, back.f_lineno, back, lock_id=str(id(frame.f_locals["self"]))) if dict_contains(frame.f_locals, "attr") and \ (frame.f_locals["attr"] in LOCK_METHODS or frame.f_locals["attr"] in QUEUE_METHODS): real_method = frame.f_locals["attr"] if method_name == "call_begin": real_method += "_begin" elif method_name == "call_end": real_method += "_end" else: return if real_method == "release_end": # do not log release end. Maybe use it later return send_message("threading_event", event_time, t.getName(), get_thread_id(t), "lock", real_method, back.f_code.co_filename, back.f_lineno, back, lock_id=str(id(self_obj))) if real_method in ("put_end", "get_end"): # fake release for queue, cause we don't call it directly send_message("threading_event", event_time, t.getName(), get_thread_id(t), "lock", "release", back.f_code.co_filename, back.f_lineno, back, lock_id=str(id(self_obj))) # print(event_time, t.getName(), get_thread_id(t), "lock", # real_method, back.f_code.co_filename, back.f_lineno) except Exception: traceback.print_exc()
def log_event(self, frame): write_log = False self_obj = None if dict_contains(frame.f_locals, "self"): self_obj = frame.f_locals["self"] if isinstance( self_obj, threading.Thread) or self_obj.__class__ == ObjectWrapper: write_log = True if hasattr(frame, "f_back") and frame.f_back is not None: back = frame.f_back if hasattr(back, "f_back") and back.f_back is not None: back = back.f_back if dict_contains(back.f_locals, "self"): if isinstance(back.f_locals["self"], threading.Thread): write_log = True try: if write_log: t = threadingCurrentThread() back = frame.f_back if not back: return _, name, back_base = pydevd_file_utils.get_abs_path_real_path_and_base_from_frame( back) event_time = cur_time() - self.start_time method_name = frame.f_code.co_name if isinstance(self_obj, threading.Thread): if not hasattr(self_obj, "_pydev_run_patched"): wrap_attr(self_obj, "run") if (method_name in THREAD_METHODS) and (back_base not in DONT_TRACE_THREADING or \ (method_name in INNER_METHODS and back_base in INNER_FILES)): thread_id = get_thread_id(self_obj) name = self_obj.getName() real_method = frame.f_code.co_name parent = None if real_method == "_stop": if back_base in INNER_FILES and \ back.f_code.co_name == "_wait_for_tstate_lock": back = back.f_back.f_back real_method = "stop" if hasattr(self_obj, "_pydev_join_called"): parent = get_thread_id(t) elif real_method == "join": # join called in the current thread, not in self object if not self_obj.is_alive(): return thread_id = get_thread_id(t) name = t.getName() setattr(self_obj, "_pydev_join_called", True) if real_method == "start": parent = get_thread_id(t) send_message("threading_event", event_time, name, thread_id, "thread", real_method, back.f_code.co_filename, back.f_lineno, back, parent=parent) # print(event_time, self_obj.getName(), thread_id, "thread", # real_method, back.f_code.co_filename, back.f_lineno) if method_name == "pydev_after_run_call": if hasattr(frame, "f_back") and frame.f_back is not None: back = frame.f_back if hasattr(back, "f_back") and back.f_back is not None: back = back.f_back if dict_contains(back.f_locals, "self"): if isinstance(back.f_locals["self"], threading.Thread): my_self_obj = frame.f_back.f_back.f_locals[ "self"] my_back = frame.f_back.f_back my_thread_id = get_thread_id(my_self_obj) send_massage = True if IS_PY3K and hasattr(my_self_obj, "_pydev_join_called"): send_massage = False # we can't detect stop after join in Python 2 yet if send_massage: send_message("threading_event", event_time, "Thread", my_thread_id, "thread", "stop", my_back.f_code.co_filename, my_back.f_lineno, my_back, parent=None) if self_obj.__class__ == ObjectWrapper: if back_base in DONT_TRACE_THREADING: # do not trace methods called from threading return back_back_base = pydevd_file_utils.get_abs_path_real_path_and_base_from_frame( back.f_back)[-1] back = back.f_back if back_back_base in DONT_TRACE_THREADING: # back_back_base is the file, where the method was called froms return if method_name == "__init__": send_message("threading_event", event_time, t.getName(), get_thread_id(t), "lock", method_name, back.f_code.co_filename, back.f_lineno, back, lock_id=str(id(frame.f_locals["self"]))) if dict_contains(frame.f_locals, "attr") and \ (frame.f_locals["attr"] in LOCK_METHODS or frame.f_locals["attr"] in QUEUE_METHODS): real_method = frame.f_locals["attr"] if method_name == "call_begin": real_method += "_begin" elif method_name == "call_end": real_method += "_end" else: return if real_method == "release_end": # do not log release end. Maybe use it later return send_message("threading_event", event_time, t.getName(), get_thread_id(t), "lock", real_method, back.f_code.co_filename, back.f_lineno, back, lock_id=str(id(self_obj))) if real_method in ("put_end", "get_end"): # fake release for queue, cause we don't call it directly send_message("threading_event", event_time, t.getName(), get_thread_id(t), "lock", "release", back.f_code.co_filename, back.f_lineno, back, lock_id=str(id(self_obj))) # print(event_time, t.getName(), get_thread_id(t), "lock", # real_method, back.f_code.co_filename, back.f_lineno) except Exception: traceback.print_exc()
def log_event(self, frame): event_time = cur_time() - self.start_time # Debug loop iterations # if isinstance(self_obj, asyncio.base_events.BaseEventLoop): # if method_name == "_run_once": # print("Loop iteration") if not hasattr(frame, "f_back") or frame.f_back is None: return back = frame.f_back if dict_contains(frame.f_locals, "self"): self_obj = frame.f_locals["self"] if isinstance(self_obj, asyncio.Task): method_name = frame.f_code.co_name if method_name == "set_result": task_id = id(self_obj) task_name = self.task_mgr.get(str(task_id)) send_message("asyncio_event", event_time, task_name, task_name, "thread", "stop", frame.f_code.co_filename, frame.f_lineno, frame) method_name = back.f_code.co_name if method_name == "__init__": task_id = id(self_obj) task_name = self.task_mgr.get(str(task_id)) send_message("asyncio_event", event_time, task_name, task_name, "thread", "start", frame.f_code.co_filename, frame.f_lineno, frame) method_name = frame.f_code.co_name if isinstance(self_obj, asyncio.Lock): if method_name in ("acquire", "release"): task_id = self.get_task_id(frame) task_name = self.task_mgr.get(str(task_id)) if method_name == "acquire": if not self_obj._waiters and not self_obj.locked(): send_message("asyncio_event", event_time, task_name, task_name, "lock", method_name+"_begin", frame.f_code.co_filename, frame.f_lineno, frame, lock_id=str(id(self_obj))) if self_obj.locked(): method_name += "_begin" else: method_name += "_end" elif method_name == "release": method_name += "_end" send_message("asyncio_event", event_time, task_name, task_name, "lock", method_name, frame.f_code.co_filename, frame.f_lineno, frame, lock_id=str(id(self_obj))) if isinstance(self_obj, asyncio.Queue): if method_name in ("put", "get", "_put", "_get"): task_id = self.get_task_id(frame) task_name = self.task_mgr.get(str(task_id)) if method_name == "put": send_message("asyncio_event", event_time, task_name, task_name, "lock", "acquire_begin", frame.f_code.co_filename, frame.f_lineno, frame, lock_id=str(id(self_obj))) elif method_name == "_put": send_message("asyncio_event", event_time, task_name, task_name, "lock", "acquire_end", frame.f_code.co_filename, frame.f_lineno, frame, lock_id=str(id(self_obj))) send_message("asyncio_event", event_time, task_name, task_name, "lock", "release", frame.f_code.co_filename, frame.f_lineno, frame, lock_id=str(id(self_obj))) elif method_name == "get": back = frame.f_back if back.f_code.co_name != "send": send_message("asyncio_event", event_time, task_name, task_name, "lock", "acquire_begin", frame.f_code.co_filename, frame.f_lineno, frame, lock_id=str(id(self_obj))) else: send_message("asyncio_event", event_time, task_name, task_name, "lock", "acquire_end", frame.f_code.co_filename, frame.f_lineno, frame, lock_id=str(id(self_obj))) send_message("asyncio_event", event_time, task_name, task_name, "lock", "release", frame.f_code.co_filename, frame.f_lineno, frame, lock_id=str(id(self_obj)))
def _get_jinja2_template_filename(frame): if dict_contains(frame.f_globals, '__jinja_template__'): fname = frame.f_globals['__jinja_template__'].filename abs_path_real_path_and_base = get_abs_path_real_path_and_base_from_file(fname) return abs_path_real_path_and_base[1] return None