(original) (raw)

changeset: 76676:96cb47f8142e branch: 3.2 parent: 76673:5c801899cd6d user: Senthil Kumaran senthil@uthcode.com date: Tue May 01 10:07:49 2012 +0800 files: Lib/bdb.py Lib/test/test_pdb.py Misc/NEWS description: issue13183 - Fix pdb skipping frames after hitting a breakpoint and running step. Patch by Xavier de Gaye diff -r 5c801899cd6d -r 96cb47f8142e Lib/bdb.py --- a/Lib/bdb.py Mon Apr 30 11:14:02 2012 -0700 +++ b/Lib/bdb.py Tue May 01 10:07:49 2012 +0800 @@ -22,6 +22,7 @@ self.skip = set(skip) if skip else None self.breaks = {} self.fncache = {} + self.frame_returning = None def canonic(self, filename): if filename == "<" + filename[1:-1] + ">": @@ -80,7 +81,11 @@ def dispatch_return(self, frame, arg): if self.stop_here(frame) or frame == self.returnframe: - self.user_return(frame, arg) + try: + self.frame_returning = frame + self.user_return(frame, arg) + finally: + self.frame_returning = None if self.quitting: raise BdbQuit return self.trace_dispatch @@ -186,6 +191,14 @@ def set_step(self): """Stop after one line of code.""" + # Issue #13183: pdb skips frames after hitting a breakpoint and running + # step commands. + # Restore the trace function in the caller (that may not have been set + # for performance reasons) when returning from the current frame. + if self.frame_returning: + caller_frame = self.frame_returning.f_back + if caller_frame and not caller_frame.f_trace: + caller_frame.f_trace = self.trace_dispatch self._set_stopinfo(None, None) def set_next(self, frame): diff -r 5c801899cd6d -r 96cb47f8142e Lib/test/test_pdb.py --- a/Lib/test/test_pdb.py Mon Apr 30 11:14:02 2012 -0700 +++ b/Lib/test/test_pdb.py Tue May 01 10:07:49 2012 +0800 @@ -5,6 +5,7 @@ import sys import unittest import subprocess +import textwrap from test import support # This little helper class is essential for testing pdb under doctest. @@ -595,6 +596,22 @@ class PdbTestCase(unittest.TestCase): + def run_pdb(self, script, commands): + """Run 'script' lines with pdb and the pdb 'commands'.""" + filename = 'main.py' + with open(filename, 'w') as f: + f.write(textwrap.dedent(script)) + cmd = [sys.executable, '-m', 'pdb', filename] + stdout = stderr = None + with subprocess.Popen(cmd, stdout=subprocess.PIPE, + stdin=subprocess.PIPE, + stderr=subprocess.STDOUT, + ) as proc: + stdout, stderr = proc.communicate(str.encode(commands)) + stdout = stdout and bytes.decode(stdout) + stderr = stderr and bytes.decode(stderr) + return stdout, stderr + def test_issue7964(self): # open the file as binary so we can force \r\n newline with open(support.TESTFN, 'wb') as f: @@ -610,6 +627,40 @@ self.assertNotIn(b'SyntaxError', stdout, "Got a syntax error running test script under PDB") + def test_issue13183(self): + script = """ + from bar import bar + + def foo(): + bar() + + def nope(): + pass + + def foobar(): + foo() + nope() + + foobar() + """ + commands = """ + from bar import bar + break bar + continue + step + step + quit + """ + bar = """ + def bar(): + print('1') + """ + with open('bar.py', 'w') as f: + f.write(textwrap.dedent(bar)) + stdout, stderr = self.run_pdb(script, commands) + self.assertIn('main.py(5)foo()->None', stdout.split('\n')[-3], + 'Fail to step into the caller after a return') + def tearDown(self): support.unlink(support.TESTFN) diff -r 5c801899cd6d -r 96cb47f8142e Misc/NEWS --- a/Misc/NEWS Mon Apr 30 11:14:02 2012 -0700 +++ b/Misc/NEWS Tue May 01 10:07:49 2012 +0800 @@ -59,6 +59,9 @@ Library ------- +- Issue #13183: Fix pdb skipping frames after hitting a breakpoint and running + step. Patch by Xavier de Gaye. + - Issue #14696: Fix parser module to understand 'nonlocal' declarations. - Issue #10941: Fix imaplib.Internaldate2tuple to produce correct result near /senthil@uthcode.com