From: Senthil Kumaran Date: Tue, 1 May 2012 02:36:28 +0000 (+0800) Subject: issue13183 - Fix pdb skipping frames after hitting a breakpoint and running step... X-Git-Tag: v2.7.4rc1~862 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7f6d4e1926a01b88be13343a82e849a90acf56e3;p=python issue13183 - Fix pdb skipping frames after hitting a breakpoint and running step. Patch by Xavier de Gaye --- diff --git a/Lib/bdb.py b/Lib/bdb.py index 6aad9793f9..1a562f47b0 100644 --- a/Lib/bdb.py +++ b/Lib/bdb.py @@ -24,6 +24,7 @@ class Bdb: 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] + ">": @@ -82,7 +83,9 @@ class Bdb: def dispatch_return(self, frame, arg): if self.stop_here(frame) or frame == self.returnframe: + self.frame_returning = frame self.user_return(frame, arg) + self.frame_returning = None if self.quitting: raise BdbQuit return self.trace_dispatch @@ -186,6 +189,14 @@ class Bdb: 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 --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py index 5a9091f795..4ab3d4d911 100644 --- a/Lib/test/test_pdb.py +++ b/Lib/test/test_pdb.py @@ -6,12 +6,66 @@ import sys import os import unittest import subprocess +import textwrap from test import test_support # This little helper class is essential for testing pdb under doctest. from test_doctest import _FakeInput +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 + proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, + stdin=subprocess.PIPE, + stderr=subprocess.STDOUT, + ) + stdout, stderr = proc.communicate(commands) + proc.stdout.close() + proc.stdin.close() + return stdout, stderr + + 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') + + class PdbTestInput(object): """Context manager that makes testing Pdb in doctests easier.""" @@ -309,7 +363,9 @@ class ModuleInitTester(unittest.TestCase): def test_main(): from test import test_pdb test_support.run_doctest(test_pdb, verbosity=True) - test_support.run_unittest(ModuleInitTester) + test_support.run_unittest( + PdbTestCase, + ModuleInitTester) if __name__ == '__main__': test_main() diff --git a/Misc/NEWS b/Misc/NEWS index a69ad3ed4d..4398e436f1 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -56,6 +56,9 @@ Core and Builtins Library ------- +- Issue #13183: Fix pdb skipping frames after hitting a breakpoint and running + step. Patch by Xavier de Gaye. + - Issue #14664: It is now possible to use @unittest.skip{If,Unless} on a test class that doesn't inherit from TestCase (i.e. a mixin).