Skip to content

Commit 63b6ec3

Browse files
gh-82987: Stop on calling frame unconditionally for inline breakpoints (#130493)
1 parent efadc58 commit 63b6ec3

File tree

5 files changed

+38
-3
lines changed

5 files changed

+38
-3
lines changed

Doc/library/pdb.rst

+4
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,10 @@ access further features, you have to do this yourself:
245245
.. versionadded:: 3.14
246246
Added the *mode* argument.
247247

248+
.. versionchanged:: 3.14
249+
Inline breakpoints like :func:`breakpoint` or :func:`pdb.set_trace` will
250+
always stop the program at calling frame, ignoring the *skip* pattern (if any).
251+
248252
.. method:: run(statement, globals=None, locals=None)
249253
runeval(expression, globals=None, locals=None)
250254
runcall(function, *args, **kwds)

Doc/whatsnew/3.14.rst

+5
Original file line numberDiff line numberDiff line change
@@ -780,6 +780,11 @@ pdb
780780
the quit and call :func:`sys.exit`, instead of raising :exc:`bdb.BdbQuit`.
781781
(Contributed by Tian Gao in :gh:`124704`.)
782782

783+
* Inline breakpoints like :func:`breakpoint` or :func:`pdb.set_trace` will
784+
always stop the program at calling frame, ignoring the ``skip`` pattern
785+
(if any).
786+
(Contributed by Tian Gao in :gh:`130493`.)
787+
783788

784789
pickle
785790
------

Lib/bdb.py

+6-3
Original file line numberDiff line numberDiff line change
@@ -215,10 +215,13 @@ def dispatch_opcode(self, frame, arg):
215215
If the debugger stops on the current opcode, invoke
216216
self.user_opcode(). Raise BdbQuit if self.quitting is set.
217217
Return self.trace_dispatch to continue tracing in this scope.
218+
219+
Opcode event will always trigger the user callback. For now the only
220+
opcode event is from an inline set_trace() and we want to stop there
221+
unconditionally.
218222
"""
219-
if self.stop_here(frame) or self.break_here(frame):
220-
self.user_opcode(frame)
221-
if self.quitting: raise BdbQuit
223+
self.user_opcode(frame)
224+
if self.quitting: raise BdbQuit
222225
return self.trace_dispatch
223226

224227
# Normally derived classes don't override the following

Lib/test/test_pdb.py

+22
Original file line numberDiff line numberDiff line change
@@ -4342,6 +4342,28 @@ def test_quit(self):
43424342
# The quit prompt should be printed exactly twice
43434343
self.assertEqual(stdout.count("Quit anyway"), 2)
43444344

4345+
def test_set_trace_with_skip(self):
4346+
"""GH-82897
4347+
Inline set_trace() should break unconditionally. This example is a
4348+
bit oversimplified, but as `pdb.set_trace()` uses the previous Pdb
4349+
instance, it's possible that we had a previous pdb instance with
4350+
skip values when we use `pdb.set_trace()` - it would be confusing
4351+
to users when such inline breakpoints won't break immediately.
4352+
"""
4353+
script = textwrap.dedent("""
4354+
import pdb
4355+
def foo():
4356+
x = 40 + 2
4357+
pdb.Pdb(skip=['__main__']).set_trace()
4358+
foo()
4359+
""")
4360+
commands = """
4361+
p x
4362+
c
4363+
"""
4364+
stdout, _ = self._run_script(script, commands)
4365+
self.assertIn("42", stdout)
4366+
43454367

43464368
@support.force_not_colorized_test_class
43474369
@support.requires_subprocess()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Inline breakpoints like :func:`breakpoint` or :func:`pdb.set_trace` will always stop the program at calling frame, ignoring the ``skip`` pattern (if any).

0 commit comments

Comments
 (0)