DebugClients/Python/DebugBase.py

branch
debugger speed
changeset 5005
684f5ba04f0b
parent 4683
1ba6ba86b383
child 5007
e2fa12bb0f53
--- a/DebugClients/Python/DebugBase.py	Thu Jun 23 19:24:09 2016 +0200
+++ b/DebugClients/Python/DebugBase.py	Sun Jun 26 16:32:01 2016 +0200
@@ -48,6 +48,13 @@
     Provides simple wrapper methods around bdb 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(bdb.__file__)
+    # tuple required because it's accessed a lot of times by startswith method
+    pathsToSkip = ('<', os.path.dirname(__file__), bdb.__file__[:-1])
+    filesToSkip = {}
+
     def __init__(self, dbgClient):
         """
         Constructor
@@ -60,6 +67,7 @@
         self._mainThread = 1
         
         self.breaks = self._dbgClient.breakpoints
+        self.tracePythonLibs(0)
         
         self.__event = ""
         self.__isBroken = ""
@@ -197,7 +205,8 @@
         @param toFrame destination frame (frame)
         """
         if self._dbgClient.callTraceEnabled:
-            if not self.__skip_it(fromFrame) and not self.__skip_it(toFrame):
+            if (not self.__skipFrame(fromFrame) and
+                    not self.__skipFrame(toFrame)):
                 if event in ["call", "return"]:
                     fr = fromFrame
                     fromStr = "%s:%s:%s" % (
@@ -248,7 +257,7 @@
             return self.trace_dispatch
         if event == 'c_return':
             return self.trace_dispatch
-        print 'DebugBase.trace_dispatch: unknown debugging event:', repr(event) # __IGNORE_WARNING__
+        print 'DebugBase.trace_dispatch: unknown debugging event:', repr(event)  # __IGNORE_WARNING__
         return self.trace_dispatch
 
     def dispatch_line(self, frame):
@@ -293,7 +302,7 @@
         @return local trace function
         @exception bdb.BdbQuit raised to indicate the end of the debug session
         """
-        if not self.__skip_it(frame):
+        if not self.__skipFrame(frame):
             self.user_exception(frame, arg)
             if self.quitting:
                 raise bdb.BdbQuit
@@ -534,8 +543,8 @@
         Because eric6 supports only one breakpoint per line, this overwritten
         method will return this one and only breakpoint.
         
-        @param filename filename of the bp to retrieve (string)
-        @param lineno linenumber of the bp to retrieve (integer)
+        @param filename the filename of the bp to retrieve (string)
+        @param lineno the linenumber of the bp to retrieve (integer)
         @return breakpoint or None, if there is no bp
         """
         filename = self.canonic(filename)
@@ -772,8 +781,8 @@
 
     def user_return(self, frame, retval):
         """
-        Public method reimplemented to report program termination to the
-        debug server.
+        Public method reimplemented to report program termination to the debug
+        server.
         
         @param frame the frame object
         @param retval the return value of the program
@@ -797,11 +806,30 @@
         @param frame the frame object
         @return flag indicating whether the debugger should stop here
         """
-        if self.__skip_it(frame):
+        if self.__skipFrame(frame):
             return 0
         return bdb.Bdb.stop_here(self, frame)
 
-    def __skip_it(self, frame):
+    def tracePythonLibs(self, enable):
+        """
+        Public methode to update the settings to trace into Python libraries.
+        
+        @param enable let's debug into Python libraries (int)
+        """
+        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.
         
@@ -811,33 +839,15 @@
         @param frame the frame object
         @return flag indicating whether the debugger should skip this frame
         """
-        if frame is None:
-            return 1
-        
-        fn = self.fix_frame_filename(frame)
-
-        # Eliminate things like <string> and <stdin>.
-        if fn[0] == '<':
-            return 1
-
-        #XXX - think of a better way to do this.  It's only a convenience for
-        #debugging the debugger - when the debugger code is in the current
-        #directory.
-        if os.path.basename(fn) in [
-            'AsyncFile.py', 'AsyncIO.py',
-            'DebugConfig.py', 'DCTestResult.py',
-            'DebugBase.py', 'DebugClientBase.py',
-            'DebugClientCapabilities.py', 'DebugClient.py',
-            'DebugClientThreads.py', 'DebugProtocol.py',
-            'DebugThread.py', 'FlexCompleter.py',
-            'PyProfile.py'] or \
-           os.path.dirname(fn).endswith("coverage"):
-            return 1
-
-        if self._dbgClient.shouldSkip(fn):
-            return 1
-        
-        return 0
+        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):
         """

eric ide

mercurial