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):