self.botframe = frame
frame = frame.f_back
self.set_step()
+ self.enterframe = None
sys.settrace(self.trace_dispatch)
def set_continue(self):
while frame and frame is not self.botframe:
del frame.f_trace
frame = frame.f_back
+ self.enterframe = None
def set_quit(self):
"""Set quitting attribute to True.
if hasattr(self, 'curframe') and self.curframe:
self.curframe.f_globals.pop('__pdb_convenience_variables', None)
self.curframe = None
+ self.curframe_locals = {}
self.tb_lineno.clear()
def setup(self, f, tb):
(Pdb) continue
"""
+def test_pdb_frame_refleak():
+ """
+ pdb should not leak reference to frames
+
+ >>> def frame_leaker(container):
+ ... import sys
+ ... container.append(sys._getframe())
+ ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
+ ... pass
+
+ >>> def test_function():
+ ... import gc
+ ... container = []
+ ... frame_leaker(container) # c
+ ... print(len(gc.get_referrers(container[0])))
+ ... container = []
+ ... frame_leaker(container) # n c
+ ... print(len(gc.get_referrers(container[0])))
+ ... container = []
+ ... frame_leaker(container) # r c
+ ... print(len(gc.get_referrers(container[0])))
+
+ >>> with PdbTestInput([ # doctest: +NORMALIZE_WHITESPACE
+ ... 'continue',
+ ... 'next',
+ ... 'continue',
+ ... 'return',
+ ... 'continue',
+ ... ]):
+ ... test_function()
+ > <doctest test.test_pdb.test_pdb_frame_refleak[0]>(5)frame_leaker()
+ -> pass
+ (Pdb) continue
+ 1
+ > <doctest test.test_pdb.test_pdb_frame_refleak[0]>(5)frame_leaker()
+ -> pass
+ (Pdb) next
+ --Return--
+ > <doctest test.test_pdb.test_pdb_frame_refleak[0]>(5)frame_leaker()->None
+ -> pass
+ (Pdb) continue
+ 1
+ > <doctest test.test_pdb.test_pdb_frame_refleak[0]>(5)frame_leaker()
+ -> pass
+ (Pdb) return
+ --Return--
+ > <doctest test.test_pdb.test_pdb_frame_refleak[0]>(5)frame_leaker()->None
+ -> pass
+ (Pdb) continue
+ 1
+ """
+
def test_pdb_issue_gh_65052():
"""See GH-65052