Skip to content

Commit f526314

Browse files
gh-58933: Make pdb return to caller frame correctly when f_trace is not set (#118979)
1 parent d8a82cc commit f526314

File tree

3 files changed

+62
-7
lines changed

3 files changed

+62
-7
lines changed

Lib/bdb.py

+9-7
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,11 @@ def dispatch_return(self, frame, arg):
165165
# The user issued a 'next' or 'until' command.
166166
if self.stopframe is frame and self.stoplineno != -1:
167167
self._set_stopinfo(None, None)
168+
# The previous frame might not have f_trace set, unless we are
169+
# issuing a command that does not expect to stop, we should set
170+
# f_trace
171+
if self.stoplineno != -1:
172+
self._set_caller_tracefunc(frame)
168173
return self.trace_dispatch
169174

170175
def dispatch_exception(self, frame, arg):
@@ -320,15 +325,14 @@ def _set_stopinfo(self, stopframe, returnframe, stoplineno=0, opcode=False):
320325
self.stoplineno = stoplineno
321326
self._set_trace_opcodes(opcode)
322327

323-
def _set_caller_tracefunc(self):
328+
def _set_caller_tracefunc(self, current_frame):
324329
# Issue #13183: pdb skips frames after hitting a breakpoint and running
325330
# step commands.
326331
# Restore the trace function in the caller (that may not have been set
327332
# for performance reasons) when returning from the current frame.
328-
if self.frame_returning:
329-
caller_frame = self.frame_returning.f_back
330-
if caller_frame and not caller_frame.f_trace:
331-
caller_frame.f_trace = self.trace_dispatch
333+
caller_frame = current_frame.f_back
334+
if caller_frame and not caller_frame.f_trace:
335+
caller_frame.f_trace = self.trace_dispatch
332336

333337
# Derived classes and clients can call the following methods
334338
# to affect the stepping state.
@@ -343,12 +347,10 @@ def set_until(self, frame, lineno=None):
343347

344348
def set_step(self):
345349
"""Stop after one line of code."""
346-
self._set_caller_tracefunc()
347350
self._set_stopinfo(None, None)
348351

349352
def set_stepinstr(self):
350353
"""Stop before the next instruction."""
351-
self._set_caller_tracefunc()
352354
self._set_stopinfo(None, None, opcode=True)
353355

354356
def set_next(self, frame):

Lib/test/test_pdb.py

+52
Original file line numberDiff line numberDiff line change
@@ -1453,6 +1453,58 @@ def test_post_mortem():
14531453
"""
14541454

14551455

1456+
def test_pdb_return_to_different_file():
1457+
"""When pdb returns to a different file, it should not skip if f_trace is
1458+
not already set
1459+
1460+
>>> import pprint
1461+
1462+
>>> class A:
1463+
... def __repr__(self):
1464+
... return 'A'
1465+
1466+
>>> def test_function():
1467+
... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
1468+
... pprint.pprint(A())
1469+
1470+
>>> reset_Breakpoint()
1471+
>>> with PdbTestInput([ # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE
1472+
... 'b A.__repr__',
1473+
... 'continue',
1474+
... 'return',
1475+
... 'next',
1476+
... 'return',
1477+
... 'return',
1478+
... 'continue',
1479+
... ]):
1480+
... test_function()
1481+
> <doctest test.test_pdb.test_pdb_return_to_different_file[2]>(2)test_function()
1482+
-> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
1483+
(Pdb) b A.__repr__
1484+
Breakpoint 1 at <doctest test.test_pdb.test_pdb_return_to_different_file[1]>:3
1485+
(Pdb) continue
1486+
> <doctest test.test_pdb.test_pdb_return_to_different_file[1]>(3)__repr__()
1487+
-> return 'A'
1488+
(Pdb) return
1489+
--Return--
1490+
> <doctest test.test_pdb.test_pdb_return_to_different_file[1]>(3)__repr__()->'A'
1491+
-> return 'A'
1492+
(Pdb) next
1493+
> ...pprint.py..._safe_repr()
1494+
-> return rep,...
1495+
(Pdb) return
1496+
--Return--
1497+
> ...pprint.py..._safe_repr()->('A'...)
1498+
-> return rep,...
1499+
(Pdb) return
1500+
--Return--
1501+
> ...pprint.py...format()->('A'...)
1502+
-> return...
1503+
(Pdb) continue
1504+
A
1505+
"""
1506+
1507+
14561508
def test_pdb_skip_modules():
14571509
"""This illustrates the simple case of module skipping.
14581510
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)