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 adfe765

Browse filesBrowse files
gh-124552 : Improve the accuracy of possible breakpoint check in bdb (#124553)
1 parent 2d8b6a4 commit adfe765
Copy full SHA for adfe765

File tree

3 files changed

+62
-3
lines changed
Filter options

3 files changed

+62
-3
lines changed

‎Lib/bdb.py

Copy file name to clipboardExpand all lines: Lib/bdb.py
+24-3Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import fnmatch
44
import sys
55
import os
6+
import weakref
67
from inspect import CO_GENERATOR, CO_COROUTINE, CO_ASYNC_GENERATOR
78

89
__all__ = ["BdbQuit", "Bdb", "Breakpoint"]
@@ -36,6 +37,7 @@ def __init__(self, skip=None):
3637
self.frame_returning = None
3738
self.trace_opcodes = False
3839
self.enterframe = None
40+
self.code_linenos = weakref.WeakKeyDictionary()
3941

4042
self._load_breaks()
4143

@@ -155,6 +157,9 @@ def dispatch_return(self, frame, arg):
155157
if self.stop_here(frame) or frame == self.returnframe:
156158
# Ignore return events in generator except when stepping.
157159
if self.stopframe and frame.f_code.co_flags & GENERATOR_AND_COROUTINE_FLAGS:
160+
# It's possible to trigger a StopIteration exception in
161+
# the caller so we must set the trace function in the caller
162+
self._set_caller_tracefunc(frame)
158163
return self.trace_dispatch
159164
try:
160165
self.frame_returning = frame
@@ -273,9 +278,25 @@ def do_clear(self, arg):
273278
raise NotImplementedError("subclass of bdb must implement do_clear()")
274279

275280
def break_anywhere(self, frame):
276-
"""Return True if there is any breakpoint for frame's filename.
281+
"""Return True if there is any breakpoint in that frame
277282
"""
278-
return self.canonic(frame.f_code.co_filename) in self.breaks
283+
filename = self.canonic(frame.f_code.co_filename)
284+
if filename not in self.breaks:
285+
return False
286+
for lineno in self.breaks[filename]:
287+
if self._lineno_in_frame(lineno, frame):
288+
return True
289+
return False
290+
291+
def _lineno_in_frame(self, lineno, frame):
292+
"""Return True if the line number is in the frame's code object.
293+
"""
294+
code = frame.f_code
295+
if lineno < code.co_firstlineno:
296+
return False
297+
if code not in self.code_linenos:
298+
self.code_linenos[code] = set(lineno for _, _, lineno in code.co_lines())
299+
return lineno in self.code_linenos[code]
279300

280301
# Derived classes should override the user_* methods
281302
# to gain control.
@@ -360,7 +381,7 @@ def set_next(self, frame):
360381
def set_return(self, frame):
361382
"""Stop when returning from the given frame."""
362383
if frame.f_code.co_flags & GENERATOR_AND_COROUTINE_FLAGS:
363-
self._set_stopinfo(frame, None, -1)
384+
self._set_stopinfo(frame, frame, -1)
364385
else:
365386
self._set_stopinfo(frame.f_back, frame)
366387

‎Lib/test/test_pdb.py

Copy file name to clipboardExpand all lines: Lib/test/test_pdb.py
+37Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,43 @@ def test_pdb_breakpoints_preserved_across_interactive_sessions():
518518
(Pdb) continue
519519
"""
520520

521+
def test_pdb_break_anywhere():
522+
"""Test break_anywhere() method of Pdb.
523+
524+
>>> def outer():
525+
... def inner():
526+
... import pdb
527+
... import sys
528+
... p = pdb.Pdb(nosigint=True, readrc=False)
529+
... p.set_trace()
530+
... frame = sys._getframe()
531+
... print(p.break_anywhere(frame)) # inner
532+
... print(p.break_anywhere(frame.f_back)) # outer
533+
... print(p.break_anywhere(frame.f_back.f_back)) # caller
534+
... inner()
535+
536+
>>> def caller():
537+
... outer()
538+
539+
>>> def test_function():
540+
... caller()
541+
542+
>>> reset_Breakpoint()
543+
>>> with PdbTestInput([ # doctest: +NORMALIZE_WHITESPACE
544+
... 'b 3',
545+
... 'c',
546+
... ]):
547+
... test_function()
548+
> <doctest test.test_pdb.test_pdb_break_anywhere[0]>(6)inner()
549+
-> p.set_trace()
550+
(Pdb) b 3
551+
Breakpoint 1 at <doctest test.test_pdb.test_pdb_break_anywhere[0]>:3
552+
(Pdb) c
553+
True
554+
False
555+
False
556+
"""
557+
521558
def test_pdb_pp_repr_exc():
522559
"""Test that do_p/do_pp do not swallow exceptions.
523560
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Improve the accuracy of :mod:`bdb`'s check for the possibility of breakpoint in a frame. This makes it possible to disable unnecessary events in functions.

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.