DebugClients/Python2/DebugBase.py

branch
debugger speed
changeset 5178
878ce843ca9f
parent 5174
8c48f5e0cd92
child 5179
5f56410e7624
diff -r 8c48f5e0cd92 -r 878ce843ca9f DebugClients/Python2/DebugBase.py
--- a/DebugClients/Python2/DebugBase.py	Sun Sep 18 21:35:53 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,949 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# Copyright (c) 2002 - 2016 Detlev Offenbach <detlev@die-offenbachs.de>
-#
-
-"""
-Module implementing the debug base class which based originally on bdb.
-"""
-
-import sys
-import os
-import types
-import atexit
-import inspect
-import ctypes
-import thread
-import time
-
-from inspect import CO_GENERATOR
-from BreakpointWatch import Breakpoint, Watch
-
-gRecursionLimit = 64
-
-
-def printerr(s):
-    """
-    Module function used for debugging the debug client.
-    
-    @param s data to be printed
-    """
-    sys.__stderr__.write('%s\n' % unicode(s))
-    sys.__stderr__.flush()
-
-
-def setRecursionLimit(limit):
-    """
-    Module function to set the recursion limit.
-    
-    @param limit recursion limit (integer)
-    """
-    global gRecursionLimit
-    gRecursionLimit = limit
-
-
-class DebugBase(object):
-    """
-    Class implementing base class of the debugger.
-
-    Provides methods for the 'owning' client to call to step etc.
-    """
-    # Don't thrust distutils.sysconfig.get_python_lib: possible case mismatch
-    #  on Windows
-    lib = os.path.dirname(inspect.__file__)
-    # tuple required because it's accessed a lot of times by startswith method
-    pathsToSkip = ('<', os.path.dirname(__file__), inspect.__file__[:-1])
-    filesToSkip = {}
-
-    # cache for fixed file names
-    _fnCache = {}
-
-    def __init__(self, dbgClient):
-        """
-        Constructor
-        
-        @param dbgClient the owning client
-        """
-        self._dbgClient = dbgClient
-        self._mainThread = True
-        self.quitting = 0
-        
-        self.tracePythonLibs(0)
-        
-        # Special handling of a recursion error
-        self.skipFrames = 0
-        
-        self.__isBroken = False
-        self.cFrame = None
-        
-        # current frame we are at
-        self.currentFrame = None
-        
-        # frame that we are stepping in, can be different than currentFrame
-        self.stepFrame = None
-        
-        self.botframe = None
-        self.stopframe = None
-        self.returnframe = None
-        self.stop_everywhere = False
-        
-        # provide a hook to perform a hard breakpoint
-        # Use it like this:
-        # if hasattr(sys, 'breakpoint): sys.breakpoint()
-        sys.breakpoint = self.set_trace
-        
-        self.__recursionDepth = -1
-        self.setRecursionDepth(inspect.currentframe())
-        
-        # background task to periodicaly check for client interactions
-        self.eventPollFlag = False
-        self.timer = thread.start_new_thread(self.__eventPollTimer, ())
-
-    def __eventPollTimer(self):
-        """
-        Private method to set a flag every 0.5 s to check for new messages.
-        """
-        while True:
-            time.sleep(0.5)
-            self.eventPollFlag = True
-    
-    def getCurrentFrame(self):
-        """
-        Public method to return the current frame.
-        
-        @return the current frame
-        """
-        return self.currentFrame
-    
-    def getFrameLocals(self, frmnr=0):
-        """
-        Public method to return the locals dictionary of the current frame
-        or a frame below.
-        
-        @keyparam frmnr distance of frame to get locals dictionary of. 0 is
-            the current frame (int)
-        @return locals dictionary of the frame
-        """
-        f = self.currentFrame
-        while f is not None and frmnr > 0:
-            f = f.f_back
-            frmnr -= 1
-        return f.f_locals
-    
-    def storeFrameLocals(self, frmnr=0):
-        """
-        Public method to store the locals into the frame, so an access to
-        frame.f_locals returns the last data.
-        
-        @keyparam frmnr distance of frame to store locals dictionary to. 0 is
-            the current frame (int)
-        """
-        cf = self.currentFrame
-        while cf is not None and frmnr > 0:
-            cf = cf.f_back
-            frmnr -= 1
-        
-        try:
-            if "__pypy__" in sys.builtin_module_names:
-                import __pypy__
-                __pypy__.locals_to_fast(cf)
-                return
-        except Exception:
-            pass
-        
-        ctypes.pythonapi.PyFrame_LocalsToFast(
-            ctypes.py_object(cf),
-            ctypes.c_int(0))
-    
-    def step(self, traceMode):
-        """
-        Public method to perform a step operation in this thread.
-        
-        @param traceMode If it is True, then the step is a step into,
-              otherwise it is a step over.
-        """
-        self.stepFrame = self.currentFrame
-        
-        if traceMode:
-            self.currentFrame = None
-            self.set_step()
-        else:
-            self.set_next(self.currentFrame)
-    
-    def stepOut(self):
-        """
-        Public method to perform a step out of the current call.
-        """
-        self.stepFrame = self.currentFrame
-        self.set_return(self.currentFrame)
-    
-    def go(self, special):
-        """
-        Public method to resume the thread.
-
-        It resumes the thread stopping only at breakpoints or exceptions.
-        
-        @param special flag indicating a special continue operation
-        """
-        self.currentFrame = None
-        self.set_continue(special)
-    
-    def setRecursionDepth(self, frame):
-        """
-        Public method to determine the current recursion depth.
-        
-        @param frame The current stack frame.
-        """
-        self.__recursionDepth = 0
-        while frame is not None:
-            self.__recursionDepth += 1
-            frame = frame.f_back
-    
-    def profileWithRecursion(self, frame, event, arg):
-        """
-        Public method used to trace some stuff independent of the debugger
-        trace function.
-        
-        @param frame current stack frame
-        @type frame object
-        @param event trace event
-        @type str
-        @param arg arguments
-        @type depends on the previous event parameter
-        @exception RuntimeError raised to indicate too many recursions
-        """
-        if event == 'return':
-            self.cFrame = frame.f_back
-            self.__recursionDepth -= 1
-            if self._dbgClient.callTraceEnabled:
-                self.__sendCallTrace(event, frame, self.cFrame)
-        elif event == 'call':
-            if self._dbgClient.callTraceEnabled:
-                self.__sendCallTrace(event, self.cFrame, frame)
-            self.cFrame = frame
-            self.__recursionDepth += 1
-            if self.__recursionDepth > gRecursionLimit:
-                raise RuntimeError(
-                    'maximum recursion depth exceeded\n'
-                    '(offending frame is two down the stack)')
-    
-    def profile(self, frame, event, arg):
-        """
-        Public method used to trace some stuff independent of the debugger
-        trace function.
-        
-        @param frame current stack frame
-        @type frame object
-        @param event trace event
-        @type str
-        @param arg arguments
-        @type depends on the previous event parameter
-        """
-        if event == 'return':
-            self.__sendCallTrace(event, frame, frame.f_back)
-        elif event == 'call':
-            self.__sendCallTrace(event, frame.f_back, frame)
-    
-    def __sendCallTrace(self, event, fromFrame, toFrame):
-        """
-        Private method to send a call/return trace.
-        
-        @param event trace event
-        @type str
-        @param fromFrame originating frame
-        @type frame object
-        @param toFrame destination frame
-        @type frame object
-        """
-        if not self.__skipFrame(fromFrame) and not self.__skipFrame(toFrame):
-            fromInfo = {
-                "filename": self._dbgClient.absPath(
-                    self.fix_frame_filename(fromFrame)),
-                "linenumber": fromFrame.f_lineno,
-                "codename": fromFrame.f_code.co_name,
-            }
-            toInfo = {
-                "filename": self._dbgClient.absPath(
-                    self.fix_frame_filename(toFrame)),
-                "linenumber": toFrame.f_lineno,
-                "codename": toFrame.f_code.co_name,
-            }
-            self._dbgClient.sendCallTrace(event, fromInfo, toInfo)
-    
-    def trace_dispatch(self, frame, event, arg):
-        """
-        Public method reimplemented from bdb.py to do some special things.
-        
-        This specialty is to check the connection to the debug server
-        for new events (i.e. new breakpoints) while we are going through
-        the code.
-        
-        @param frame The current stack frame
-        @type frame object
-        @param event The trace event
-        @type str
-        @param arg The arguments
-        @type depends on the previous event parameter
-        @return local trace function
-        @rtype trace function or None
-        @exception SystemExit
-        """
-        # give the client a chance to push through new break points.
-        if self.eventPollFlag:
-            self._dbgClient.eventPoll()
-            self.eventPollFlag = False
-            
-            if self.quitting:
-                raise SystemExit
-        
-        if event == 'line':
-            if self.stop_here(frame) or self.break_here(frame):
-                self.user_line(frame)
-            return
-        
-        if event == 'call':
-            if self.botframe is None and frame.f_lineno > 1:
-                self.botframe = frame.f_back
-                frame.f_trace = self.trace_dispatch
-                self._dbgClient.mainFrame = frame
-                
-                self.user_line(frame)
-                return self.trace_dispatch
-            
-            if not (self.stop_here(frame) or
-                    self.__checkBreakInFrame(frame) or
-                    Watch.watches != []):
-                # No need to trace this function
-                return
-            return self.trace_dispatch
-        
-        if event == 'return':
-            if self.stop_here(frame):
-                # Ignore return events in generator except when stepping.
-                if self.stopframe and frame.f_code.co_flags & CO_GENERATOR:
-                    return
-                # The program has finished if we have just left the first frame
-                if (frame == self._dbgClient.mainFrame and
-                        self._mainThread):
-                    atexit._run_exitfuncs()
-                    self._dbgClient.progTerminated(arg)
-                
-                if self.quitting and not self._dbgClient.passive:
-                    raise SystemExit
-            return
-        
-        if event == 'exception':
-            if not self.__skipFrame(frame):
-                # When stepping with next/until/return in a generator frame,
-                # skip the internal StopIteration exception (with no traceback)
-                # triggered by a subiterator run with the 'yield from'
-                # statement.
-                if not (frame.f_code.co_flags & CO_GENERATOR and
-                        arg[0] is StopIteration and arg[2] is None):
-                    self.user_exception(frame, arg)
-            # Stop at the StopIteration or GeneratorExit exception when the
-            # user has set stopframe in a generator by issuing a return
-            # command, or a next/until command at the last statement in the
-            # generator before the exception.
-            elif (self.stopframe and frame is not self.stopframe and
-                    self.stopframe.f_code.co_flags & CO_GENERATOR and
-                    arg[0] in (StopIteration, GeneratorExit)):
-                self.user_exception(frame, arg)
-            return
-
-        if event == 'c_call':
-            return
-        if event == 'c_exception':
-            return
-        if event == 'c_return':
-            return
-        
-        print('DebugBase.trace_dispatch:'       # __IGNORE_WARNING__
-              ' unknown debugging event: ',
-              repr(event))
-        return self.trace_dispatch
-
-    def set_trace(self, frame=None):
-        """
-        Public method to start debugging from 'frame'.
-
-        If frame is not specified, debugging starts from caller's frame.
-        Because of jump optimizations it's not possible to use sys.breakpoint()
-        as last instruction in a function or method.
-        
-        @keyparam frame frame to start debugging from
-        @type frame object
-        """
-        if frame is None:
-            frame = sys._getframe().f_back  # Skip set_trace method
-        
-        frame.f_trace = self.trace_dispatch
-        while frame is not None:
-            # stop at erics debugger frame
-            if frame.f_back.f_code == self._dbgClient.handleLine.func_code:
-                frame.f_trace = self.trace_dispatch
-                self.botframe = frame
-                self._dbgClient.mainFrame = frame
-                break
-            
-            frame = frame.f_back
-        
-        self.stop_everywhere = True
-        sys.settrace(self.trace_dispatch)
-        sys.setprofile(self._dbgClient.callTraceEnabled)
-    
-    def run(self, cmd, globals=None, locals=None):
-        """
-        Public method to start a given command under debugger control.
-        
-        @param cmd command / code to execute under debugger control
-        @type str or CodeType
-        @keyparam globals dictionary of global variables for cmd
-        @type dict
-        @keyparam locals  dictionary of local variables for cmd
-        @type dict
-        """
-        if globals is None:
-            import __main__
-            globals = __main__.__dict__
-        
-        if locals is None:
-            locals = globals
-        
-        sys.settrace(self.trace_dispatch)
-        if not isinstance(cmd, types.CodeType):
-            cmd += '\n'
-        
-        try:
-            exec cmd in globals, locals
-        except SystemExit:
-            pass
-        finally:
-            self.quitting = 1
-            sys.settrace(None)
-
-    def _set_stopinfo(self, stopframe, returnframe):
-        """
-        Protected method to update the frame pointers.
-        
-        @param stopframe the frame object where to stop
-        @type frame object
-        @param returnframe the frame object where to stop on a function return
-        @type frame object
-        """
-        self.stopframe = stopframe
-        self.returnframe = returnframe
-        self.stop_everywhere = False
-
-    def set_continue(self, special):
-        """
-        Public method to stop only on next breakpoint.
-        
-        @param special flag indicating a special continue operation
-        @type bool
-        """
-        # Here we only set a new stop frame if it is a normal continue.
-        if not special:
-            self._set_stopinfo(self.botframe, None)
-        
-        # Disable tracing if not started in debug mode
-        if not self._dbgClient.debugging:
-            sys.settrace(None)
-            sys.setprofile(None)
-
-    def set_step(self):
-        """
-        Public method to stop after one line of code.
-        """
-        self._set_stopinfo(None, None)
-        self.stop_everywhere = True
-
-    def set_next(self, frame):
-        """
-        Public method to stop on the next line in or below the given frame.
-        
-        @param frame the frame object
-        @type frame object
-        """
-        self._set_stopinfo(frame, frame.f_back)
-        frame.f_back.f_trace = self.trace_dispatch
-        frame.f_trace = self.trace_dispatch
-
-    def set_return(self, frame):
-        """
-        Public method to stop when returning from the given frame.
-        
-        @param frame the frame object
-        @type frame object
-        """
-        self._set_stopinfo(None, frame.f_back)
-
-    def set_quit(self):
-        """
-        Public method to quit.
-        
-        Disables the trace functions and resets all frame pointer.
-        """
-        self.currentFrame = None
-        sys.setprofile(None)
-        sys.settrace(None)
-        self.stopframe = None
-        self.returnframe = None
-        self.quitting = 1
-    
-    def fix_frame_filename(self, frame):
-        """
-        Public method used to fixup the filename for a given frame.
-        
-        The logic employed here is that if a module was loaded
-        from a .pyc file, then the correct .py to operate with
-        should be in the same path as the .pyc. The reason this
-        logic is needed is that when a .pyc file is generated, the
-        filename embedded and thus what is readable in the code object
-        of the frame object is the fully qualified filepath when the
-        pyc is generated. If files are moved from machine to machine
-        this can break debugging as the .pyc will refer to the .py
-        on the original machine. Another case might be sharing
-        code over a network... This logic deals with that.
-        
-        @param frame the frame object
-        @type frame object
-        @return fixed up file name
-        @rtype str
-        """
-        # get module name from __file__
-        fn = frame.f_globals.get('__file__')
-        try:
-            return self._fnCache[fn]
-        except KeyError:
-            if fn and fn != frame.f_code.co_filename:
-                absFilename = os.path.abspath(fn)
-                if absFilename.endswith(('.pyc', '.pyo')):
-                    fixedName = absFilename[:-1]
-                    if not os.path.exists(fixedName):
-                        fixedName = absFilename
-                else:
-                    fixedName = absFilename
-            else:
-                fixedName = frame.f_code.co_filename
-            # update cache
-            self._fnCache[fn] = fixedName
-            return fixedName
-
-    def __checkBreakInFrame(self, frame):
-        """
-        Private method to check if the function / method has a line number
-        which is a breakpoint.
-        
-        @param frame the frame object
-        @type frame object
-        @return Flag indicating a function / method with breakpoint
-        @rtype bool
-        """
-        try:
-            return Breakpoint.breakInFrameCache[
-                frame.f_globals.get('__file__'),
-                frame.f_code.co_firstlineno]
-        except KeyError:
-            filename = self.fix_frame_filename(frame)
-            if filename not in Breakpoint.breakInFile:
-                Breakpoint.breakInFrameCache[
-                    frame.f_globals.get('__file__'),
-                    frame.f_code.co_firstlineno] = False
-                return False
-            lineNo = frame.f_code.co_firstlineno
-            lineNumbers = [lineNo]
-            # No need to handle special case if a lot of lines between
-            # (e.g. closure), because the additional lines won't cause a bp
-            for co_lno in frame.f_code.co_lnotab[1::2]:
-                lineNo += ord(co_lno)
-                lineNumbers.append(lineNo)
-            
-            for bp in Breakpoint.breakInFile[filename]:
-                if bp in lineNumbers:
-                    Breakpoint.breakInFrameCache[
-                        frame.f_globals.get('__file__'),
-                        frame.f_code.co_firstlineno] = True
-                    return True
-            Breakpoint.breakInFrameCache[
-                frame.f_globals.get('__file__'),
-                frame.f_code.co_firstlineno] = False
-            return False
-    
-    def break_here(self, frame):
-        """
-        Public method reimplemented from bdb.py to fix the filename from the
-        frame.
-        
-        See fix_frame_filename for more info.
-        
-        @param frame the frame object
-        @type frame object
-        @return flag indicating the break status
-        @rtype bool
-        """
-        filename = self.fix_frame_filename(frame)
-        if (filename, frame.f_lineno) in Breakpoint.breaks:
-            bp, flag = Breakpoint.effectiveBreak(
-                filename, frame.f_lineno, frame)
-            if bp:
-                # flag says ok to delete temp. bp
-                if flag and bp.temporary:
-                    self.__do_clearBreak(filename, frame.f_lineno)
-                return True
-        
-        if Watch.watches != []:
-            bp, flag = Watch.effectiveWatch(frame)
-            if bp:
-                # flag says ok to delete temp. watch
-                if flag and bp.temporary:
-                    self.__do_clearWatch(bp.cond)
-                return True
-        
-        return False
-
-    def __do_clearBreak(self, filename, lineno):
-        """
-        Private method called to clear a temporary breakpoint.
-        
-        @param filename name of the file the bp belongs to
-        @type str
-        @param lineno linenumber of the bp
-        @type int
-        """
-        Breakpoint.clear_break(filename, lineno)
-        self._dbgClient.sendClearTemporaryBreakpoint(filename, lineno)
-
-    def __do_clearWatch(self, cond):
-        """
-        Private method called to clear a temporary watch expression.
-        
-        @param cond expression of the watch expression to be cleared
-        @type str
-        """
-        Watch.clear_watch(cond)
-        self._dbgClient.sendClearTemporaryWatch(cond)
-
-    def getStack(self):
-        """
-        Public method to get the stack.
-        
-        @return list of lists with file name (string), line number (integer)
-            and function name (string)
-        """
-        fr = self.cFrame
-        stack = []
-        while fr is not None:
-            fname = self._dbgClient.absPath(self.fix_frame_filename(fr))
-            if not fname.startswith("<"):
-                fline = fr.f_lineno
-                ffunc = fr.f_code.co_name
-                
-                if ffunc == '?':
-                    ffunc = ''
-                
-                if ffunc and not ffunc.startswith("<"):
-                    argInfo = inspect.getargvalues(fr)
-                    try:
-                        fargs = inspect.formatargvalues(argInfo[0], argInfo[1],
-                                                        argInfo[2], argInfo[3])
-                    except Exception:
-                        fargs = ""
-                else:
-                    fargs = ""
-                
-                stack.append([fname, fline, ffunc, fargs])
-            
-            if fr == self._dbgClient.mainFrame:
-                fr = None
-            else:
-                fr = fr.f_back
-        
-        return stack
-    
-    def user_line(self, frame):
-        """
-        Public method reimplemented to handle the program about to execute a
-        particular line.
-        
-        @param frame the frame object
-        """
-        # We never stop on line 0.
-        if frame.f_lineno == 0:
-            return
-        
-        self.currentFrame = frame
-        
-        fr = frame
-        stack = []
-        while fr is not None:
-            # Reset the trace function so we can be sure
-            # to trace all functions up the stack... This gets around
-            # problems where an exception/breakpoint has occurred
-            # but we had disabled tracing along the way via a None
-            # return from dispatch_call
-            fr.f_trace = self.trace_dispatch
-            fname = self._dbgClient.absPath(self.fix_frame_filename(fr))
-            if not fname.startswith("<"):
-                fline = fr.f_lineno
-                ffunc = fr.f_code.co_name
-                
-                if ffunc == '?':
-                    ffunc = ''
-                
-                if ffunc and not ffunc.startswith("<"):
-                    argInfo = inspect.getargvalues(fr)
-                    try:
-                        fargs = inspect.formatargvalues(argInfo[0], argInfo[1],
-                                                        argInfo[2], argInfo[3])
-                    except Exception:
-                        fargs = ""
-                else:
-                    fargs = ""
-                
-                stack.append([fname, fline, ffunc, fargs])
-            
-            if fr == self._dbgClient.mainFrame:
-                fr = None
-            else:
-                fr = fr.f_back
-        
-        self.__isBroken = True
-        
-        self._dbgClient.sendResponseLine(stack)
-        self._dbgClient.eventLoop()
-        
-        self.__isBroken = False
-
-    def user_exception(self, frame, (exctype, excval, exctb), unhandled=False):
-        """
-        Public method reimplemented to report an exception to the debug server.
-        
-        @param frame the frame object
-        @type frame object
-        @param exctype the type of the exception
-        @type Exception
-        @param excval data about the exception
-        @type excval object
-        @param exctb traceback for the exception
-        @type traceback frame object
-        @keyparam unhandled flag indicating an uncaught exception
-        @type bool
-        """
-        if exctype in [GeneratorExit, StopIteration]:
-            # ignore these
-            return
-        
-        if exctype == SystemExit:
-            atexit._run_exitfuncs()
-            if excval is None:
-                exitcode = 0
-                message = ""
-            elif isinstance(excval, (unicode, str)):
-                exitcode = 1
-                message = excval
-            elif isinstance(excval, int):
-                exitcode = excval
-                message = ""
-            elif isinstance(excval, SystemExit):
-                code = excval.code
-                if isinstance(code, (unicode, str)):
-                    exitcode = 1
-                    message = code
-                elif isinstance(code, int):
-                    exitcode = code
-                    message = ""
-                else:
-                    exitcode = 1
-                    message = str(code)
-            else:
-                exitcode = 1
-                message = str(excval)
-            self._dbgClient.progTerminated(exitcode, message)
-            return
-        
-        if exctype in [SyntaxError, IndentationError]:
-            try:
-                message = unicode(excval)
-                try:
-                    message = unicode(excval).encode(
-                        self._dbgClient.getCoding())
-                except UnicodeError:
-                    message = str(excval)
-                filename = excval.filename
-                lineno = excval.lineno
-                charno = excval.offset
-                realSyntaxError = os.path.exists(filename)
-            except (AttributeError, ValueError):
-                message = ""
-                filename = ""
-                lineno = 0
-                charno = 0
-                realSyntaxError = True
-            
-            if realSyntaxError:
-                self._dbgClient.sendSyntaxError(
-                    message, filename, lineno, charno)
-                self._dbgClient.eventLoop()
-                return
-        
-        self.skipFrames = 0
-        if (exctype == RuntimeError and
-                str(excval).startswith('maximum recursion depth exceeded')):
-            excval = 'maximum recursion depth exceeded'
-            depth = 0
-            tb = exctb
-            while tb:
-                tb = tb.tb_next
-                
-                if (tb and tb.tb_frame.f_code.co_name == 'trace_dispatch' and
-                        __file__.startswith(tb.tb_frame.f_code.co_filename)):
-                    depth = 1
-                self.skipFrames += depth
-        
-        if type(exctype) in [types.ClassType,   # Python up to 2.4
-                             types.TypeType]:   # Python 2.5+
-            exctype = exctype.__name__
-        
-        if excval is None:
-            excval = ''
-        
-        if unhandled:
-            exctypetxt = "unhandled %s" % unicode(exctype)
-        else:
-            exctypetxt = unicode(exctype)
-        
-        try:
-            excvaltxt = unicode(excval).encode(self._dbgClient.getCoding())
-        except UnicodeError:
-            excvaltxt = str(excval)
-        
-        stack = []
-        if exctb:
-            frlist = self.__extract_stack(exctb)
-            frlist.reverse()
-            
-            self.currentFrame = frlist[0]
-            
-            for fr in frlist[self.skipFrames:]:
-                filename = self._dbgClient.absPath(self.fix_frame_filename(fr))
-                
-                if os.path.basename(filename).startswith("DebugClientBase"):
-                    break
-                
-                linenr = fr.f_lineno
-                ffunc = fr.f_code.co_name
-                
-                if ffunc == '?':
-                    ffunc = ''
-                
-                if ffunc and not ffunc.startswith("<"):
-                    argInfo = inspect.getargvalues(fr)
-                    try:
-                        fargs = inspect.formatargvalues(argInfo[0], argInfo[1],
-                                                        argInfo[2], argInfo[3])
-                    except Exception:
-                        fargs = ""
-                else:
-                    fargs = ""
-                
-                stack.append([filename, linenr, ffunc, fargs])
-        
-        self._dbgClient.sendException(exctypetxt, excvaltxt, stack)
-        
-        if exctb is None:
-            return
-        
-        self._dbgClient.eventLoop()
-        self.skipFrames = 0
-    
-    def __extract_stack(self, exctb):
-        """
-        Private member to return a list of stack frames.
-        
-        @param exctb exception traceback
-        @return list of stack frames
-        """
-        tb = exctb
-        stack = []
-        while tb is not None:
-            stack.append(tb.tb_frame)
-            tb = tb.tb_next
-        tb = None
-        return stack
-
-    def stop_here(self, frame):
-        """
-        Public method reimplemented to filter out debugger files.
-        
-        Tracing is turned off for files that are part of the
-        debugger that are called from the application being debugged.
-        
-        @param frame the frame object
-        @type frame object
-        @return flag indicating whether the debugger should stop here
-        @rtype bool
-        """
-        if self.__skipFrame(frame):
-            return False
-        
-        return (self.stop_everywhere or
-                frame is self.stopframe or
-                frame is self.returnframe or
-                frame is self.botframe)
-
-    def tracePythonLibs(self, enable):
-        """
-        Public method to update the settings to trace into Python libraries.
-        
-        @param enable flag to debug into Python libraries
-        @type bool
-        """
-        pathsToSkip = list(self.pathsToSkip)
-        # don't trace into Python library?
-        if enable:
-            pathsToSkip = [x for x in pathsToSkip if not x.endswith(
-                ("site-packages", "dist-packages", self.lib))]
-        else:
-            pathsToSkip.append(self.lib)
-            localLib = [x for x in sys.path if x.endswith(("site-packages",
-                        "dist-packages")) and not x.startswith(self.lib)]
-            pathsToSkip.extend(localLib)
-        
-        self.pathsToSkip = tuple(pathsToSkip)
-
-    def __skipFrame(self, frame):
-        """
-        Private method to filter out debugger files.
-        
-        Tracing is turned off for files that are part of the
-        debugger that are called from the application being debugged.
-        
-        @param frame the frame object
-        @type frame object
-        @return flag indicating whether the debugger should skip this frame
-        @rtype bool
-        """
-        try:
-            return self.filesToSkip[frame.f_code.co_filename]
-        except KeyError:
-            ret = frame.f_code.co_filename.startswith(self.pathsToSkip)
-            self.filesToSkip[frame.f_code.co_filename] = ret
-            return ret
-        except AttributeError:
-            # if frame is None
-            return True
-    
-    def isBroken(self):
-        """
-        Public method to return the broken state of the debugger.
-        
-        @return flag indicating the broken state
-        @rtype bool
-        """
-        return self.__isBroken
-
-
-#
-# eflag: FileType = Python2
-# eflag: noqa = M601, M702

eric ide

mercurial