src/eric7/DebugClients/Python/DebugBase.py

branch
eric7
changeset 9542
0b04348749ab
parent 9482
a2bc06a54d9d
child 9559
34fc53e6159d
diff -r 69167c94995f -r 0b04348749ab src/eric7/DebugClients/Python/DebugBase.py
--- a/src/eric7/DebugClients/Python/DebugBase.py	Sun Nov 27 17:47:20 2022 +0100
+++ b/src/eric7/DebugClients/Python/DebugBase.py	Sun Nov 27 17:59:59 2022 +0100
@@ -95,6 +95,8 @@
 
         # current frame we are at
         self.currentFrame = None
+        self.frameList = []
+        self.getStack()
 
         # frames, where we want to stop or release debugger
         self.stopframe = None
@@ -125,10 +127,13 @@
 
         self.eventPollFlag = False
 
-    def getCurrentFrame(self):
+    def getFrame(self, frmnr=0):
         """
-        Public method to return the current frame.
+        Public method to return the frame "frmnr" down the stack.
 
+        @param frmnr distance of frames down the stack. 0 is
+            the current frame
+        @rtype int
         @return the current frame
         @rtype frame object
         """
@@ -136,7 +141,10 @@
         if self.quitting:
             return None
 
-        return self.currentFrame
+        try:
+            return self.frameList[frmnr]
+        except IndexError:
+            return None
 
     def getFrameLocals(self, frmnr=0):
         """
@@ -147,11 +155,11 @@
             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
+        try:
+            f = self.frameList[frmnr]
+            return f.f_locals
+        except IndexError:
+            return {}
 
     def storeFrameLocals(self, frmnr=0):
         """
@@ -161,10 +169,7 @@
         @param 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
+        cf = self.frameList[frmnr]
 
         with contextlib.suppress(ImportError, AttributeError):
             if "__pypy__" in sys.builtin_module_names:
@@ -763,14 +768,16 @@
         """
         tb_lineno = None
         if frame is None:
-            fr = self.getCurrentFrame()
+            fr = self.getFrame()
         elif type(frame) == list:
             fr, tb_lineno = frame.pop(0)
         else:
             fr = frame
 
+        self.frameList.clear()
         stack = []
         while fr is not None:
+            self.frameList.append(fr)
             if applyTrace:
                 # Reset the trace function so we can be sure
                 # to trace all functions up the stack... This gets around
@@ -843,6 +850,8 @@
         self._dbgClient.sendResponseLine(stack, self.name)
         self._dbgClient.eventLoop()
 
+        self.frameList.clear()
+
         self.isBroken = False
         self._dbgClient.unlockClient()
 
@@ -897,6 +906,7 @@
                     message, filename, lineno, charno, self.name
                 )
                 self._dbgClient.eventLoop()
+                self.frameList.clear()
                 return
 
         self.skipFrames = 0
@@ -961,6 +971,7 @@
             # unhandled exception without further user interaction.
             self._dbgClient.eventLoop(True)
 
+        self.frameList.clear()
         self.skipFrames = 0
 
         self.isBroken = False
@@ -995,7 +1006,15 @@
         while tb is not None:
             stack.append((tb.tb_frame, tb.tb_lineno))
             tb = tb.tb_next
-        tb = None
+
+        # Follow first frame to bottom to catch special case if an exception
+        # is thrown in a function with breakpoint in it.
+        # eric's frames are filtered out later by self.getStack
+        frame = stack[0][0].f_back
+        while frame is not None:
+            stack.insert(0, (frame, frame.f_lineno))
+            frame = frame.f_back
+
         return stack
 
     def __disassemble(self, frame):

eric ide

mercurial