Skip to content

Comments

gh-50571: Check bytecode before accepting a breakpoint in pdb#145121

Open
aisk wants to merge 4 commits intopython:mainfrom
aisk:pdb-break-nocode
Open

gh-50571: Check bytecode before accepting a breakpoint in pdb#145121
aisk wants to merge 4 commits intopython:mainfrom
aisk:pdb-break-nocode

Conversation

@aisk
Copy link
Member

@aisk aisk commented Feb 22, 2026

Collect all linenos in a code object recursively, and check if the target breakpoint is in them. If not, report an error, just like set break point on blank lines.

fname = db1.canonic(__file__)
db1.set_break(__file__, 1)
self.assertEqual(db1.get_all_breaks(), {fname: [1]})
db1.set_break(__file__, 51)
Copy link
Member Author

@aisk aisk Feb 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These change are because the old position is just doc strings which don't have an associate bytecode, so it will cause error. Change them to L51 which have a real statement.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add some comments here saying this test is sensitive to the test file itself. So people won't get confused if they add something in the header comment and make the test fail. Just explain that the corresponding line numbers have to be associated with byte codes.

Copy link
Member

@gaogaotiantian gaogaotiantian left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall I think it's a good fix. Also relatively safe. I have a few commonts.

if lineno is not None:
linenos.add(lineno)
for const in code.co_consts:
if hasattr(const, 'co_lines'):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's check isinstance(const, CodeType) (from types) instead of co_lines.

line = linecache.getline(filename, lineno)
if not line:
return 'Line %s:%d does not exist' % (filename, lineno)
source = ''.join(linecache.getlines(filename))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's cache this internally. Build a {filename: lineno} cache. Having some overhead for setting breakpoint is fine, but compile + co_lines() is pretty expensive. Let's avoid wasting extra time on it.

@@ -0,0 +1,3 @@
:mod:`bdb` will reports an error when set breakpoint on a line with no
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
:mod:`bdb` will reports an error when set breakpoint on a line with no
:mod:`bdb` will report an error when setting breakpoint on a line with no

fname = db1.canonic(__file__)
db1.set_break(__file__, 1)
self.assertEqual(db1.get_all_breaks(), {fname: [1]})
db1.set_break(__file__, 51)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add some comments here saying this test is sensitive to the test file itself. So people won't get confused if they add something in the header comment and make the test fail. Just explain that the corresponding line numbers have to be associated with byte codes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants