Skip to content

Commit

Permalink
pythongh-59013: Make line number of function breakpoint more precise (p…
Browse files Browse the repository at this point in the history
  • Loading branch information
gaogaotiantian authored and aisk committed Feb 11, 2024
1 parent 221cbcd commit 5c271de
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 3 deletions.
19 changes: 18 additions & 1 deletion Lib/pdb.py
Expand Up @@ -887,7 +887,7 @@ def do_break(self, arg, temporary = 0):
#use co_name to identify the bkpt (function names
#could be aliased, but co_name is invariant)
funcname = code.co_name
lineno = code.co_firstlineno
lineno = self._find_first_executable_line(code)
filename = code.co_filename
except:
# last thing to try
Expand Down Expand Up @@ -990,6 +990,23 @@ def checkline(self, filename, lineno):
return 0
return lineno

def _find_first_executable_line(self, code):
""" Try to find the first executable line of the code object.
Equivalently, find the line number of the instruction that's
after RESUME
Return code.co_firstlineno if no executable line is found.
"""
prev = None
for instr in dis.get_instructions(code):
if prev is not None and prev.opname == 'RESUME':
if instr.positions.lineno is not None:
return instr.positions.lineno
return code.co_firstlineno
prev = instr
return code.co_firstlineno

def do_enable(self, arg):
"""enable bpnumber [bpnumber ...]
Expand Down
46 changes: 44 additions & 2 deletions Lib/test/test_pdb.py
Expand Up @@ -1516,7 +1516,7 @@ def test_next_until_return_at_return_event():
> <doctest test.test_pdb.test_next_until_return_at_return_event[1]>(3)test_function()
-> test_function_2()
(Pdb) break test_function_2
Breakpoint 1 at <doctest test.test_pdb.test_next_until_return_at_return_event[0]>:1
Breakpoint 1 at <doctest test.test_pdb.test_next_until_return_at_return_event[0]>:2
(Pdb) continue
> <doctest test.test_pdb.test_next_until_return_at_return_event[0]>(2)test_function_2()
-> x = 1
Expand Down Expand Up @@ -1938,7 +1938,7 @@ def test_pdb_next_command_in_generator_for_loop():
> <doctest test.test_pdb.test_pdb_next_command_in_generator_for_loop[1]>(3)test_function()
-> for i in test_gen():
(Pdb) break test_gen
Breakpoint 1 at <doctest test.test_pdb.test_pdb_next_command_in_generator_for_loop[0]>:1
Breakpoint 1 at <doctest test.test_pdb.test_pdb_next_command_in_generator_for_loop[0]>:2
(Pdb) continue
> <doctest test.test_pdb.test_pdb_next_command_in_generator_for_loop[0]>(2)test_gen()
-> yield 0
Expand Down Expand Up @@ -2350,6 +2350,48 @@ def test_pdb_ambiguous_statements():
(Pdb) continue
"""

def test_pdb_function_break():
"""Testing the line number of break on function
>>> def foo(): pass
>>> def bar():
...
... pass
>>> def boo():
... # comments
... global x
... x = 1
>>> def gen():
... yield 42
>>> def test_function():
... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
... pass
>>> with PdbTestInput([ # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
... 'break foo',
... 'break bar',
... 'break boo',
... 'break gen',
... 'continue'
... ]):
... test_function()
> <doctest test.test_pdb.test_pdb_function_break[4]>(3)test_function()
-> pass
(Pdb) break foo
Breakpoint ... at <doctest test.test_pdb.test_pdb_function_break[0]>:1
(Pdb) break bar
Breakpoint ... at <doctest test.test_pdb.test_pdb_function_break[1]>:3
(Pdb) break boo
Breakpoint ... at <doctest test.test_pdb.test_pdb_function_break[2]>:4
(Pdb) break gen
Breakpoint ... at <doctest test.test_pdb.test_pdb_function_break[3]>:2
(Pdb) continue
"""

def test_pdb_issue_gh_65052():
"""See GH-65052
Expand Down
@@ -0,0 +1 @@
Make line number of function breakpoint more precise in :mod:`pdb`

0 comments on commit 5c271de

Please sign in to comment.