Skip to content

Commit

Permalink
[3.12] gh-58933: Make pdb return to caller frame correctly when f_tra…
Browse files Browse the repository at this point in the history
…ce is not set (GH-118979) (#119008)

* [3.12] gh-58933: Make pdb return to caller frame correctly when f_trace is not set (GH-118979)
(cherry picked from commit f526314)

Co-authored-by: Tian Gao <gaogaotiantian@hotmail.com>
  • Loading branch information
gaogaotiantian authored May 13, 2024
1 parent 2430729 commit fcdd20e
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 8 deletions.
22 changes: 14 additions & 8 deletions Lib/bdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,11 @@ def dispatch_return(self, frame, arg):
# The user issued a 'next' or 'until' command.
if self.stopframe is frame and self.stoplineno != -1:
self._set_stopinfo(None, None)
# The previous frame might not have f_trace set, unless we are
# issuing a command that does not expect to stop, we should set
# f_trace
if self.stoplineno != -1:
self._set_caller_tracefunc(frame)
return self.trace_dispatch

def dispatch_exception(self, frame, arg):
Expand Down Expand Up @@ -286,6 +291,15 @@ def _set_stopinfo(self, stopframe, returnframe, stoplineno=0):
# stoplineno -1 means: don't stop at all
self.stoplineno = stoplineno

def _set_caller_tracefunc(self, current_frame):
# 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.
caller_frame = current_frame.f_back
if caller_frame and not caller_frame.f_trace:
caller_frame.f_trace = self.trace_dispatch

# Derived classes and clients can call the following methods
# to affect the stepping state.

Expand All @@ -299,14 +313,6 @@ def set_until(self, frame, lineno=None):

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):
Expand Down
52 changes: 52 additions & 0 deletions Lib/test/test_pdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -904,6 +904,58 @@ def test_post_mortem():
"""


def test_pdb_return_to_different_file():
"""When pdb returns to a different file, it should not skip if f_trace is
not already set
>>> import pprint
>>> class A:
... def __repr__(self):
... return 'A'
>>> def test_function():
... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
... pprint.pprint(A())
>>> reset_Breakpoint()
>>> with PdbTestInput([ # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE
... 'b A.__repr__',
... 'continue',
... 'return',
... 'next',
... 'return',
... 'return',
... 'continue',
... ]):
... test_function()
> <doctest test.test_pdb.test_pdb_return_to_different_file[2]>(3)test_function()
-> pprint.pprint(A())
(Pdb) b A.__repr__
Breakpoint 1 at <doctest test.test_pdb.test_pdb_return_to_different_file[1]>:2
(Pdb) continue
> <doctest test.test_pdb.test_pdb_return_to_different_file[1]>(3)__repr__()
-> return 'A'
(Pdb) return
--Return--
> <doctest test.test_pdb.test_pdb_return_to_different_file[1]>(3)__repr__()->'A'
-> return 'A'
(Pdb) next
> ...pprint.py..._safe_repr()
-> return rep,...
(Pdb) return
--Return--
> ...pprint.py..._safe_repr()->('A'...)
-> return rep,...
(Pdb) return
--Return--
> ...pprint.py...format()->('A'...)
-> return...
(Pdb) continue
A
"""


def test_pdb_skip_modules():
"""This illustrates the simple case of module skipping.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Make :mod:`pdb` return to caller frame correctly when ``f_trace`` of the caller frame is not set

0 comments on commit fcdd20e

Please sign in to comment.