def create_db_frame(self, args): #the frame must be cached as a weak-ref (we return the actual db frame -- which will be kept #alive until its trace_dispatch method is not referenced anymore). #that's a large workaround because: #1. we can't have weak-references to python frame object #2. only from 2.5 onwards we have _current_frames support from the interpreter db_frame = PyDBFrame(args) db_frame.frame = args[-1] self._AddDbFrame(db_frame) return db_frame
def __call__(self, frame, event, arg): ''' This is the callback used when we enter some context in the debugger. We also decorate the thread we are in with info about the debugging. The attributes added are: pydev_state pydev_step_stop pydev_step_cmd pydev_notify_kill :param PyDB py_db: This is the global debugger (this method should actually be added as a method to it). ''' # IFDEF CYTHON # cdef str filename; # cdef str base; # cdef int pydev_step_cmd; # cdef tuple frame_cache_key; # cdef dict cache_skips; # cdef bint is_stepping; # cdef tuple abs_path_real_path_and_base; # cdef PyDBAdditionalThreadInfo additional_info; # ENDIF # print('ENTER: trace_dispatch', frame.f_code.co_filename, frame.f_lineno, event, frame.f_code.co_name) py_db, t, additional_info, cache_skips, frame_skips_cache = self._args pydev_step_cmd = additional_info.pydev_step_cmd is_stepping = pydev_step_cmd != -1 try: if py_db._finish_debugging_session: if not py_db._termination_event_set: # that was not working very well because jython gave some socket errors try: if py_db.output_checker is None: kill_all_pydev_threads() except: traceback.print_exc() py_db._termination_event_set = True return None # if thread is not alive, cancel trace_dispatch processing if not is_thread_alive(t): py_db.notify_thread_not_alive(get_thread_id(t)) return None # suspend tracing if py_db.thread_analyser is not None: py_db.thread_analyser.log_event(frame) if py_db.asyncio_analyser is not None: py_db.asyncio_analyser.log_event(frame) # Note: it's important that the context name is also given because we may hit something once # in the global context and another in the local context. frame_cache_key = (frame.f_code.co_firstlineno, frame.f_code.co_name, frame.f_code.co_filename) if not is_stepping and frame_cache_key in cache_skips: # print('skipped: trace_dispatch (cache hit)', frame_cache_key, frame.f_lineno, event, frame.f_code.co_name) return None try: # Make fast path faster! abs_path_real_path_and_base = NORM_PATHS_AND_BASE_CONTAINER[frame.f_code.co_filename] except: abs_path_real_path_and_base = get_abs_path_real_path_and_base_from_frame(frame) filename = abs_path_real_path_and_base[1] file_type = get_file_type(abs_path_real_path_and_base[-1]) #we don't want to debug threading or anything related to pydevd if file_type is not None: if file_type == 1: # inlining LIB_FILE = 1 if not py_db.in_project_scope(filename): # print('skipped: trace_dispatch (not in scope)', abs_path_real_path_and_base[-1], frame.f_lineno, event, frame.f_code.co_name, file_type) cache_skips[frame_cache_key] = 1 return None else: # print('skipped: trace_dispatch', abs_path_real_path_and_base[-1], frame.f_lineno, event, frame.f_code.co_name, file_type) cache_skips[frame_cache_key] = 1 return None if is_stepping: if py_db.is_filter_enabled and py_db.is_ignored_by_filters(filename): # ignore files matching stepping filters return None if py_db.is_filter_libraries and not py_db.in_project_scope(filename): # ignore library files while stepping return None # print('trace_dispatch', base, frame.f_lineno, event, frame.f_code.co_name, file_type) if additional_info.is_tracing: return None # we don't wan't to trace code invoked from pydevd_frame.trace_dispatch # Just create PyDBFrame directly (removed support for Python versions < 2.5, which required keeping a weak # reference to the frame). ret = PyDBFrame( ( py_db, filename, additional_info, t, frame_skips_cache, frame_cache_key, ) ).trace_dispatch(frame, event, arg) if ret is None: cache_skips[frame_cache_key] = 1 return None # IFDEF CYTHON # return SafeCallWrapper(ret) # ELSE return ret # ENDIF except SystemExit: return None except Exception: if py_db._finish_debugging_session: return None # Don't log errors when we're shutting down. # Log it try: if traceback is not None: # This can actually happen during the interpreter shutdown in Python 2.7 traceback.print_exc() except: # Error logging? We're really in the interpreter shutdown... # (https://github.com/fabioz/PyDev.Debugger/issues/8) pass return None
def __call__(self, frame, event, arg): ''' This is the callback used when we enter some context in the debugger. We also decorate the thread we are in with info about the debugging. The attributes added are: pydev_state pydev_step_stop pydev_step_cmd pydev_notify_kill :param PyDB py_db: This is the global debugger (this method should actually be added as a method to it). ''' # IFDEF CYTHON # cdef str filename; # cdef str base; # cdef int pydev_step_cmd; # cdef tuple frame_cache_key; # cdef dict cache_skips; # cdef bint is_stepping; # cdef tuple abs_path_canonical_path_and_base; # cdef PyDBAdditionalThreadInfo additional_info; # ENDIF # DEBUG = 'code_to_debug' in frame.f_code.co_filename # if DEBUG: print('ENTER: trace_dispatch: %s %s %s %s' % (frame.f_code.co_filename, frame.f_lineno, event, frame.f_code.co_name)) py_db, t, additional_info, cache_skips, frame_skips_cache = self._args if additional_info.is_tracing: return None if event == 'call' else NO_FTRACE # we don't wan't to trace code invoked from pydevd_frame.trace_dispatch additional_info.is_tracing += 1 try: pydev_step_cmd = additional_info.pydev_step_cmd is_stepping = pydev_step_cmd != -1 if py_db.pydb_disposed: return None if event == 'call' else NO_FTRACE # if thread is not alive, cancel trace_dispatch processing if not is_thread_alive(t): py_db.notify_thread_not_alive(get_current_thread_id(t)) return None if event == 'call' else NO_FTRACE # Note: it's important that the context name is also given because we may hit something once # in the global context and another in the local context. frame_cache_key = (frame.f_code.co_firstlineno, frame.f_code.co_name, frame.f_code.co_filename) if frame_cache_key in cache_skips: if not is_stepping: # if DEBUG: print('skipped: trace_dispatch (cache hit)', frame_cache_key, frame.f_lineno, event, frame.f_code.co_name) return None if event == 'call' else NO_FTRACE else: # When stepping we can't take into account caching based on the breakpoints (only global filtering). if cache_skips.get(frame_cache_key) == 1: if additional_info.pydev_original_step_cmd in (CMD_STEP_INTO, CMD_STEP_INTO_MY_CODE) and not _global_notify_skipped_step_in: notify_skipped_step_in_because_of_filters(py_db, frame) back_frame = frame.f_back if back_frame is not None and pydev_step_cmd in (CMD_STEP_INTO, CMD_STEP_INTO_MY_CODE, CMD_STEP_RETURN, CMD_STEP_RETURN_MY_CODE): back_frame_cache_key = (back_frame.f_code.co_firstlineno, back_frame.f_code.co_name, back_frame.f_code.co_filename) if cache_skips.get(back_frame_cache_key) == 1: # if DEBUG: print('skipped: trace_dispatch (cache hit: 1)', frame_cache_key, frame.f_lineno, event, frame.f_code.co_name) return None if event == 'call' else NO_FTRACE else: # if DEBUG: print('skipped: trace_dispatch (cache hit: 2)', frame_cache_key, frame.f_lineno, event, frame.f_code.co_name) return None if event == 'call' else NO_FTRACE try: # Make fast path faster! abs_path_canonical_path_and_base = NORM_PATHS_AND_BASE_CONTAINER[frame.f_code.co_filename] except: abs_path_canonical_path_and_base = get_abs_path_real_path_and_base_from_frame(frame) file_type = py_db.get_file_type(frame, abs_path_canonical_path_and_base) # we don't want to debug threading or anything related to pydevd if file_type is not None: if file_type == 1: # inlining LIB_FILE = 1 if not py_db.in_project_scope(frame, abs_path_canonical_path_and_base[0]): # if DEBUG: print('skipped: trace_dispatch (not in scope)', abs_path_canonical_path_and_base[2], frame.f_lineno, event, frame.f_code.co_name, file_type) cache_skips[frame_cache_key] = 1 return None if event == 'call' else NO_FTRACE else: # if DEBUG: print('skipped: trace_dispatch', abs_path_canonical_path_and_base[2], frame.f_lineno, event, frame.f_code.co_name, file_type) cache_skips[frame_cache_key] = 1 return None if event == 'call' else NO_FTRACE if py_db.is_files_filter_enabled: if py_db.apply_files_filter(frame, abs_path_canonical_path_and_base[0], False): cache_skips[frame_cache_key] = 1 if is_stepping and additional_info.pydev_original_step_cmd in (CMD_STEP_INTO, CMD_STEP_INTO_MY_CODE) and not _global_notify_skipped_step_in: notify_skipped_step_in_because_of_filters(py_db, frame) # A little gotcha, sometimes when we're stepping in we have to stop in a # return event showing the back frame as the current frame, so, we need # to check not only the current frame but the back frame too. back_frame = frame.f_back if back_frame is not None and pydev_step_cmd in (CMD_STEP_INTO, CMD_STEP_INTO_MY_CODE, CMD_STEP_RETURN, CMD_STEP_RETURN_MY_CODE): if py_db.apply_files_filter(back_frame, back_frame.f_code.co_filename, False): back_frame_cache_key = (back_frame.f_code.co_firstlineno, back_frame.f_code.co_name, back_frame.f_code.co_filename) cache_skips[back_frame_cache_key] = 1 # if DEBUG: print('skipped: trace_dispatch (filtered out: 1)', frame_cache_key, frame.f_lineno, event, frame.f_code.co_name) return None if event == 'call' else NO_FTRACE else: # if DEBUG: print('skipped: trace_dispatch (filtered out: 2)', frame_cache_key, frame.f_lineno, event, frame.f_code.co_name) return None if event == 'call' else NO_FTRACE # if DEBUG: print('trace_dispatch', filename, frame.f_lineno, event, frame.f_code.co_name, file_type) # Just create PyDBFrame directly (removed support for Python versions < 2.5, which required keeping a weak # reference to the frame). ret = PyDBFrame( ( py_db, abs_path_canonical_path_and_base, additional_info, t, frame_skips_cache, frame_cache_key, ) ).trace_dispatch(frame, event, arg) if ret is None: # 1 means skipped because of filters. # 2 means skipped because no breakpoints were hit. cache_skips[frame_cache_key] = 2 return None if event == 'call' else NO_FTRACE # IFDEF CYTHON # frame.f_trace = SafeCallWrapper(ret) # Make sure we keep the returned tracer. # ELSE frame.f_trace = ret # Make sure we keep the returned tracer. # ENDIF return ret except SystemExit: return None if event == 'call' else NO_FTRACE except Exception: if py_db.pydb_disposed: return None if event == 'call' else NO_FTRACE # Don't log errors when we're shutting down. # Log it try: if pydev_log_exception is not None: # This can actually happen during the interpreter shutdown in Python 2.7 pydev_log_exception() except: # Error logging? We're really in the interpreter shutdown... # (https://github.com/fabioz/PyDev.Debugger/issues/8) pass return None if event == 'call' else NO_FTRACE finally: additional_info.is_tracing -= 1