Skip to content

Commit fcdd20e

Browse files
[3.12] gh-58933: Make pdb return to caller frame correctly when f_trace 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>
1 parent 2430729 commit fcdd20e

File tree

3 files changed

+67
-8
lines changed

3 files changed

+67
-8
lines changed

Diff for: Lib/bdb.py

+14-8
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,11 @@ def dispatch_return(self, frame, arg):
157157
# The user issued a 'next' or 'until' command.
158158
if self.stopframe is frame and self.stoplineno != -1:
159159
self._set_stopinfo(None, None)
160+
# The previous frame might not have f_trace set, unless we are
161+
# issuing a command that does not expect to stop, we should set
162+
# f_trace
163+
if self.stoplineno != -1:
164+
self._set_caller_tracefunc(frame)
160165
return self.trace_dispatch
161166

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

294+
def _set_caller_tracefunc(self, current_frame):
295+
# Issue #13183: pdb skips frames after hitting a breakpoint and running
296+
# step commands.
297+
# Restore the trace function in the caller (that may not have been set
298+
# for performance reasons) when returning from the current frame.
299+
caller_frame = current_frame.f_back
300+
if caller_frame and not caller_frame.f_trace:
301+
caller_frame.f_trace = self.trace_dispatch
302+
289303
# Derived classes and clients can call the following methods
290304
# to affect the stepping state.
291305

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

300314
def set_step(self):
301315
"""Stop after one line of code."""
302-
# Issue #13183: pdb skips frames after hitting a breakpoint and running
303-
# step commands.
304-
# Restore the trace function in the caller (that may not have been set
305-
# for performance reasons) when returning from the current frame.
306-
if self.frame_returning:
307-
caller_frame = self.frame_returning.f_back
308-
if caller_frame and not caller_frame.f_trace:
309-
caller_frame.f_trace = self.trace_dispatch
310316
self._set_stopinfo(None, None)
311317

312318
def set_next(self, frame):

Diff for: Lib/test/test_pdb.py

+52
Original file line numberDiff line numberDiff line change
@@ -904,6 +904,58 @@ def test_post_mortem():
904904
"""
905905

906906

907+
def test_pdb_return_to_different_file():
908+
"""When pdb returns to a different file, it should not skip if f_trace is
909+
not already set
910+
911+
>>> import pprint
912+
913+
>>> class A:
914+
... def __repr__(self):
915+
... return 'A'
916+
917+
>>> def test_function():
918+
... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
919+
... pprint.pprint(A())
920+
921+
>>> reset_Breakpoint()
922+
>>> with PdbTestInput([ # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE
923+
... 'b A.__repr__',
924+
... 'continue',
925+
... 'return',
926+
... 'next',
927+
... 'return',
928+
... 'return',
929+
... 'continue',
930+
... ]):
931+
... test_function()
932+
> <doctest test.test_pdb.test_pdb_return_to_different_file[2]>(3)test_function()
933+
-> pprint.pprint(A())
934+
(Pdb) b A.__repr__
935+
Breakpoint 1 at <doctest test.test_pdb.test_pdb_return_to_different_file[1]>:2
936+
(Pdb) continue
937+
> <doctest test.test_pdb.test_pdb_return_to_different_file[1]>(3)__repr__()
938+
-> return 'A'
939+
(Pdb) return
940+
--Return--
941+
> <doctest test.test_pdb.test_pdb_return_to_different_file[1]>(3)__repr__()->'A'
942+
-> return 'A'
943+
(Pdb) next
944+
> ...pprint.py..._safe_repr()
945+
-> return rep,...
946+
(Pdb) return
947+
--Return--
948+
> ...pprint.py..._safe_repr()->('A'...)
949+
-> return rep,...
950+
(Pdb) return
951+
--Return--
952+
> ...pprint.py...format()->('A'...)
953+
-> return...
954+
(Pdb) continue
955+
A
956+
"""
957+
958+
907959
def test_pdb_skip_modules():
908960
"""This illustrates the simple case of module skipping.
909961
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Make :mod:`pdb` return to caller frame correctly when ``f_trace`` of the caller frame is not set

0 commit comments

Comments
 (0)