Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
[3.12] gh-58933: Make pdb return to caller frame correctly when f_tra…
…ce is not set (GH-118979)

(cherry picked from commit f526314)

Co-authored-by: Tian Gao <gaogaotiantian@hotmail.com>
  • Loading branch information
gaogaotiantian committed May 13, 2024
commit 966acfec0c43d774a13eb2ed968553455a163188
27 changes: 27 additions & 0 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 @@ -285,6 +290,19 @@ def _set_stopinfo(self, stopframe, returnframe, stoplineno=0):
# stoplineno >= 0 means: stop at line >= the stoplineno
# stoplineno -1 means: don't stop at all
self.stoplineno = stoplineno
<<<<<<< HEAD
=======
self._set_trace_opcodes(opcode)

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
>>>>>>> f526314194... gh-58933: Make pdb return to caller frame correctly when f_trace is not set (#118979)

# Derived classes and clients can call the following methods
# to affect the stepping state.
Expand All @@ -299,6 +317,7 @@ def set_until(self, frame, lineno=None):

def set_step(self):
"""Stop after one line of code."""
<<<<<<< HEAD
# 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
Expand All @@ -309,6 +328,14 @@ def set_step(self):
caller_frame.f_trace = self.trace_dispatch
self._set_stopinfo(None, None)

=======
self._set_stopinfo(None, None)

def set_stepinstr(self):
"""Stop before the next instruction."""
self._set_stopinfo(None, None, opcode=True)

>>>>>>> f526314194... gh-58933: Make pdb return to caller frame correctly when f_trace is not set (#118979)
def set_next(self, frame):
"""Stop on the next line in or below the given frame."""
self._set_stopinfo(frame, None)
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]>(2)test_function()
-> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
(Pdb) b A.__repr__
Breakpoint 1 at <doctest test.test_pdb.test_pdb_return_to_different_file[1]>:3
(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