DebugClients/Python3/DebugBase.py

branch
debugger speed
changeset 5005
684f5ba04f0b
parent 4830
f609a22f43bd
child 5007
e2fa12bb0f53
--- a/DebugClients/Python3/DebugBase.py	Thu Jun 23 19:24:09 2016 +0200
+++ b/DebugClients/Python3/DebugBase.py	Sun Jun 26 16:32:01 2016 +0200
@@ -49,6 +49,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
@@ -61,6 +68,7 @@
         self._mainThread = True
         
         self.breaks = self._dbgClient.breakpoints
+        self.tracePythonLibs(0)
         
         self.__event = ""
         self.__isBroken = ""
@@ -198,7 +206,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 = "{0}:{1}:{2}".format(
@@ -297,7 +306,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):
             # 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'
@@ -845,12 +854,31 @@
         @param frame the frame object
         @return flag indicating whether the debugger should stop here
         """
-        if self.__skip_it(frame):
+        if self.__skipFrame(frame):
             return False
         
         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.
         
@@ -860,33 +888,15 @@
         @param frame the frame object
         @return flag indicating whether the debugger should skip this frame
         """
-        if frame is None:
-            return True
-        
-        fn = self.fix_frame_filename(frame)
-
-        # Eliminate things like <string> and <stdin>.
-        if fn[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
-
-        #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 True
-
-        if self._dbgClient.shouldSkip(fn):
-            return True
-        
-        return False
     
     def isBroken(self):
         """

eric ide

mercurial