mirror of
https://github.com/python/cpython.git
synced 2025-09-15 05:06:12 +00:00
Fix issue #1689458 by teaching frame_setlineno how to jump to the first line of
a code object.
This commit is contained in:
parent
cf4ad76a0a
commit
c8d30fec16
2 changed files with 41 additions and 14 deletions
|
@ -740,6 +740,27 @@ class JumpTestCase(unittest.TestCase):
|
||||||
def test_19_no_jump_without_trace_function(self):
|
def test_19_no_jump_without_trace_function(self):
|
||||||
no_jump_without_trace_function()
|
no_jump_without_trace_function()
|
||||||
|
|
||||||
|
def test_jump_to_firstlineno(self):
|
||||||
|
# This tests that PDB can jump back to the first line in a
|
||||||
|
# file. See issue #1689458. It can only be triggered in a
|
||||||
|
# function call if the function is defined on a single line.
|
||||||
|
code = compile("""
|
||||||
|
# Comments don't count.
|
||||||
|
output.append(2) # firstlineno is here.
|
||||||
|
output.append(3)
|
||||||
|
output.append(4)
|
||||||
|
""", "<fake module>", "exec")
|
||||||
|
class fake_function:
|
||||||
|
func_code = code
|
||||||
|
jump = (2, 0)
|
||||||
|
tracer = JumpTracer(fake_function)
|
||||||
|
sys.settrace(tracer.trace)
|
||||||
|
namespace = {"output": []}
|
||||||
|
exec code in namespace
|
||||||
|
sys.settrace(None)
|
||||||
|
self.compare_jump_output([2, 3, 2, 3, 4], namespace["output"])
|
||||||
|
|
||||||
|
|
||||||
def test_main():
|
def test_main():
|
||||||
test_support.run_unittest(
|
test_support.run_unittest(
|
||||||
TraceTestCase,
|
TraceTestCase,
|
||||||
|
|
|
@ -140,20 +140,26 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno)
|
||||||
new_lineno);
|
new_lineno);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
else if (new_lineno == f->f_code->co_firstlineno) {
|
||||||
/* Find the bytecode offset for the start of the given line, or the
|
new_lasti = 0;
|
||||||
* first code-owning line after it. */
|
new_lineno = f->f_code->co_firstlineno;
|
||||||
PyString_AsStringAndSize(f->f_code->co_lnotab, &lnotab, &lnotab_len);
|
}
|
||||||
addr = 0;
|
else {
|
||||||
line = f->f_code->co_firstlineno;
|
/* Find the bytecode offset for the start of the given
|
||||||
new_lasti = -1;
|
* line, or the first code-owning line after it. */
|
||||||
for (offset = 0; offset < lnotab_len; offset += 2) {
|
PyString_AsStringAndSize(f->f_code->co_lnotab,
|
||||||
addr += lnotab[offset];
|
&lnotab, &lnotab_len);
|
||||||
line += lnotab[offset+1];
|
addr = 0;
|
||||||
if (line >= new_lineno) {
|
line = f->f_code->co_firstlineno;
|
||||||
new_lasti = addr;
|
new_lasti = -1;
|
||||||
new_lineno = line;
|
for (offset = 0; offset < lnotab_len; offset += 2) {
|
||||||
break;
|
addr += lnotab[offset];
|
||||||
|
line += lnotab[offset+1];
|
||||||
|
if (line >= new_lineno) {
|
||||||
|
new_lasti = addr;
|
||||||
|
new_lineno = line;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue