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 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
Beispiel #3
0
    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
Beispiel #4
0
    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