Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit fcdd20e

Browse filesBrowse 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
Copy full SHA for fcdd20e

File tree

3 files changed

+67
-8
lines changed
Filter options

3 files changed

+67
-8
lines changed

‎Lib/bdb.py

Copy file name to clipboardExpand all lines: Lib/bdb.py
+14-8Lines changed: 14 additions & 8 deletions
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):

‎Lib/test/test_pdb.py

Copy file name to clipboardExpand all lines: Lib/test/test_pdb.py
+52Lines changed: 52 additions & 0 deletions
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
+1Lines changed: 1 addition & 0 deletions
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 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.