bdb.py

来自「mallet是自然语言处理、机器学习领域的一个开源项目。」· Python 代码 · 共 564 行 · 第 1/2 页

PY
564
字号
"""Debugger basics"""import sysimport osimport types__all__ = ["BdbQuit","Bdb","Breakpoint"]BdbQuit = 'bdb.BdbQuit' # Exception to give up completelyclass Bdb:    """Generic Python debugger base class.    This class takes care of details of the trace facility;    a derived class should implement user interaction.    The standard debugger class (pdb.Pdb) is an example.    """    def __init__(self):        self.breaks = {}        self.fncache = {}    def canonic(self, filename):        if filename == "<" + filename[1:-1] + ">":            return filename        canonic = self.fncache.get(filename)        if not canonic:            canonic = os.path.abspath(filename)            canonic = os.path.normcase(canonic)            self.fncache[filename] = canonic        return canonic    def reset(self):        import linecache        linecache.checkcache()        self.botframe = None        self.stopframe = None        self.returnframe = None        self.quitting = 0    def trace_dispatch(self, frame, event, arg):        if self.quitting:            return # None        if event == 'line':            return self.dispatch_line(frame)        if event == 'call':            return self.dispatch_call(frame, arg)        if event == 'return':            return self.dispatch_return(frame, arg)        if event == 'exception':            return self.dispatch_exception(frame, arg)        print 'bdb.Bdb.dispatch: unknown debugging event:', `event`        return self.trace_dispatch    def dispatch_line(self, frame):        if self.stop_here(frame) or self.break_here(frame):            self.user_line(frame)            if self.quitting: raise BdbQuit        return self.trace_dispatch    def dispatch_call(self, frame, arg):        # XXX 'arg' is no longer used        if self.botframe is None:            # First call of dispatch since reset()            self.botframe = frame.f_back # (CT) Note that this may also be None!            return self.trace_dispatch        if not (self.stop_here(frame) or self.break_anywhere(frame)):            # No need to trace this function            return # None        self.user_call(frame, arg)        if self.quitting: raise BdbQuit        return self.trace_dispatch    def dispatch_return(self, frame, arg):        if self.stop_here(frame) or frame == self.returnframe:            self.user_return(frame, arg)            if self.quitting: raise BdbQuit        return self.trace_dispatch    def dispatch_exception(self, frame, arg):        if self.stop_here(frame):            self.user_exception(frame, arg)            if self.quitting: raise BdbQuit        return self.trace_dispatch    # Normally derived classes don't override the following    # methods, but they may if they want to redefine the    # definition of stopping and breakpoints.    def stop_here(self, frame):        # (CT) stopframe may now also be None, see dispatch_call.        # (CT) the former test for None is therefore removed from here.        if frame is self.stopframe:            return 1        while frame is not None and frame is not self.stopframe:            if frame is self.botframe:                return 1            frame = frame.f_back        return 0    def break_here(self, frame):        filename = self.canonic(frame.f_code.co_filename)        if not self.breaks.has_key(filename):            return 0        lineno = frame.f_lineno        if not lineno in self.breaks[filename]:            return 0        # flag says ok to delete temp. bp        (bp, flag) = effective(filename, lineno, frame)        if bp:            self.currentbp = bp.number            if (flag and bp.temporary):                self.do_clear(str(bp.number))            return 1        else:            return 0    def do_clear(self, arg):        raise NotImplementedError, "subclass of bdb must implement do_clear()"    def break_anywhere(self, frame):        return self.breaks.has_key(            self.canonic(frame.f_code.co_filename))    # Derived classes should override the user_* methods    # to gain control.    def user_call(self, frame, argument_list):        """This method is called when there is the remote possibility        that we ever need to stop in this function."""        pass    def user_line(self, frame):        """This method is called when we stop or break at this line."""        pass    def user_return(self, frame, return_value):        """This method is called when a return trap is set here."""        pass    def user_exception(self, frame, (exc_type, exc_value, exc_traceback)):        """This method is called if an exception occurs,        but only if we are to stop at or just below this level."""        pass    # Derived classes and clients can call the following methods    # to affect the stepping state.    def set_step(self):        """Stop after one line of code."""        self.stopframe = None        self.returnframe = None        self.quitting = 0    def set_next(self, frame):        """Stop on the next line in or below the given frame."""        self.stopframe = frame        self.returnframe = None        self.quitting = 0    def set_return(self, frame):        """Stop when returning from the given frame."""        self.stopframe = frame.f_back        self.returnframe = frame        self.quitting = 0    def set_trace(self):        """Start debugging from here."""        frame = sys._getframe().f_back        self.reset()        while frame:            frame.f_trace = self.trace_dispatch            self.botframe = frame            frame = frame.f_back        self.set_step()        sys.settrace(self.trace_dispatch)    def set_continue(self):        # Don't stop except at breakpoints or when finished        self.stopframe = self.botframe        self.returnframe = None        self.quitting = 0        if not self.breaks:            # no breakpoints; run without debugger overhead            sys.settrace(None)            frame = sys._getframe().f_back            while frame and frame is not self.botframe:                del frame.f_trace                frame = frame.f_back    def set_quit(self):        self.stopframe = self.botframe        self.returnframe = None        self.quitting = 1        sys.settrace(None)    # Derived classes and clients can call the following methods    # to manipulate breakpoints.  These methods return an    # error message is something went wrong, None if all is well.    # Set_break prints out the breakpoint line and file:lineno.    # Call self.get_*break*() to see the breakpoints or better    # for bp in Breakpoint.bpbynumber: if bp: bp.bpprint().    def set_break(self, filename, lineno, temporary=0, cond = None):        filename = self.canonic(filename)        import linecache # Import as late as possible        line = linecache.getline(filename, lineno)        if not line:            return 'Line %s:%d does not exist' % (filename,                                   lineno)        if not self.breaks.has_key(filename):            self.breaks[filename] = []        list = self.breaks[filename]        if not lineno in list:            list.append(lineno)        bp = Breakpoint(filename, lineno, temporary, cond)    def clear_break(self, filename, lineno):        filename = self.canonic(filename)        if not self.breaks.has_key(filename):            return 'There are no breakpoints in %s' % filename        if lineno not in self.breaks[filename]:            return 'There is no breakpoint at %s:%d' % (filename,                                    lineno)        # If there's only one bp in the list for that file,line        # pair, then remove the breaks entry        for bp in Breakpoint.bplist[filename, lineno][:]:            bp.deleteMe()        if not Breakpoint.bplist.has_key((filename, lineno)):            self.breaks[filename].remove(lineno)        if not self.breaks[filename]:            del self.breaks[filename]    def clear_bpbynumber(self, arg):        try:            number = int(arg)        except:            return 'Non-numeric breakpoint number (%s)' % arg        try:            bp = Breakpoint.bpbynumber[number]        except IndexError:            return 'Breakpoint number (%d) out of range' % number        if not bp:            return 'Breakpoint (%d) already deleted' % number        self.clear_break(bp.file, bp.line)    def clear_all_file_breaks(self, filename):        filename = self.canonic(filename)        if not self.breaks.has_key(filename):            return 'There are no breakpoints in %s' % filename        for line in self.breaks[filename]:            blist = Breakpoint.bplist[filename, line]            for bp in blist:                bp.deleteMe()        del self.breaks[filename]    def clear_all_breaks(self):        if not self.breaks:            return 'There are no breakpoints'        for bp in Breakpoint.bpbynumber:            if bp:                bp.deleteMe()        self.breaks = {}    def get_break(self, filename, lineno):        filename = self.canonic(filename)        return self.breaks.has_key(filename) and \            lineno in self.breaks[filename]    def get_breaks(self, filename, lineno):        filename = self.canonic(filename)        return self.breaks.has_key(filename) and \            lineno in self.breaks[filename] and \            Breakpoint.bplist[filename, lineno] or []    def get_file_breaks(self, filename):        filename = self.canonic(filename)        if self.breaks.has_key(filename):            return self.breaks[filename]        else:

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?