import sys
import os
import weakref
+from contextlib import contextmanager
from inspect import CO_GENERATOR, CO_COROUTINE, CO_ASYNC_GENERATOR
__all__ = ["BdbQuit", "Bdb", "Breakpoint"]
self.botframe = None
self._set_stopinfo(None, None)
+ @contextmanager
+ def set_enterframe(self, frame):
+ self.enterframe = frame
+ yield
+ self.enterframe = None
+
def trace_dispatch(self, frame, event, arg):
"""Dispatch a trace function for debugged frames based on the event.
The arg parameter depends on the previous event.
"""
- self.enterframe = frame
-
- if self.quitting:
- return # None
- if event == 'line':
- return self.dispatch_line(frame)
- if event == 'call':
- return self.dispatch_call(frame, arg)
- if event == 'return':
- return self.dispatch_return(frame, arg)
- if event == 'exception':
- return self.dispatch_exception(frame, arg)
- if event == 'c_call':
- return self.trace_dispatch
- if event == 'c_exception':
- return self.trace_dispatch
- if event == 'c_return':
+ with self.set_enterframe(frame):
+ if self.quitting:
+ return # None
+ if event == 'line':
+ return self.dispatch_line(frame)
+ if event == 'call':
+ return self.dispatch_call(frame, arg)
+ if event == 'return':
+ return self.dispatch_return(frame, arg)
+ if event == 'exception':
+ return self.dispatch_exception(frame, arg)
+ if event == 'c_call':
+ return self.trace_dispatch
+ if event == 'c_exception':
+ return self.trace_dispatch
+ if event == 'c_return':
+ return self.trace_dispatch
+ if event == 'opcode':
+ return self.dispatch_opcode(frame, arg)
+ print('bdb.Bdb.dispatch: unknown debugging event:', repr(event))
return self.trace_dispatch
- if event == 'opcode':
- return self.dispatch_opcode(frame, arg)
- print('bdb.Bdb.dispatch: unknown debugging event:', repr(event))
- return self.trace_dispatch
def dispatch_line(self, frame):
"""Invoke user function and return trace function for line event.
if frame is None:
frame = sys._getframe().f_back
self.reset()
- self.enterframe = frame
- while frame:
- frame.f_trace = self.trace_dispatch
- self.botframe = frame
- self.frame_trace_lines_opcodes[frame] = (frame.f_trace_lines, frame.f_trace_opcodes)
- # We need f_trace_lines == True for the debugger to work
- frame.f_trace_lines = True
- frame = frame.f_back
- self.set_stepinstr()
- self.enterframe = None
+ with self.set_enterframe(frame):
+ while frame:
+ frame.f_trace = self.trace_dispatch
+ self.botframe = frame
+ self.frame_trace_lines_opcodes[frame] = (frame.f_trace_lines, frame.f_trace_opcodes)
+ # We need f_trace_lines == True for the debugger to work
+ frame.f_trace_lines = True
+ frame = frame.f_back
+ self.set_stepinstr()
sys.settrace(self.trace_dispatch)
def set_continue(self):
for frame, (trace_lines, trace_opcodes) in self.frame_trace_lines_opcodes.items():
frame.f_trace_lines, frame.f_trace_opcodes = trace_lines, trace_opcodes
self.frame_trace_lines_opcodes = {}
- self.enterframe = None
def set_quit(self):
"""Set quitting attribute to True.