mirror of
https://github.com/python/cpython
synced 2026-09-29 11:55:30 +03:00
Merged revisions 72776,72796 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk ........ r72776 | jeffrey.yasskin | 2009-05-18 14:14:54 -0700 (Mon, 18 May 2009) | 6 lines While I was modifying test_trace, it threw an exception when I accidentally made it try to set the line number from the trace callback for a 'call' event. This patch makes the error message a little more helpful in that case, and makes it a little less likely that a future editor will make the same mistake in test_trace. ........ r72796 | jeffrey.yasskin | 2009-05-20 10:57:57 -0700 (Wed, 20 May 2009) | 3 lines Fix issue #1689458 by teaching frame_setlineno how to jump to the first line of a code object. ........
This commit is contained in:
parent
787ab172c9
commit
4db6ff683d
2 changed files with 44 additions and 16 deletions
|
|
@ -472,7 +472,7 @@ class JumpTracer:
|
|||
def trace(self, frame, event, arg):
|
||||
if not self.done and frame.f_code == self.function.__code__:
|
||||
firstLine = frame.f_code.co_firstlineno
|
||||
if frame.f_lineno == firstLine + self.jumpFrom:
|
||||
if event == 'line' and frame.f_lineno == firstLine + self.jumpFrom:
|
||||
# Cope with non-integer self.jumpTo (because of
|
||||
# no_jump_to_non_integers below).
|
||||
try:
|
||||
|
|
@ -741,6 +741,27 @@ class JumpTestCase(unittest.TestCase):
|
|||
def test_19_no_jump_without_trace_function(self):
|
||||
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:
|
||||
__code__ = code
|
||||
jump = (2, 0)
|
||||
tracer = JumpTracer(fake_function)
|
||||
sys.settrace(tracer.trace)
|
||||
namespace = {"output": []}
|
||||
exec(code, namespace)
|
||||
sys.settrace(None)
|
||||
self.compare_jump_output([2, 3, 2, 3, 4], namespace["output"])
|
||||
|
||||
|
||||
def test_main():
|
||||
support.run_unittest(
|
||||
TraceTestCase,
|
||||
|
|
|
|||
|
|
@ -98,7 +98,8 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno)
|
|||
if (!f->f_trace)
|
||||
{
|
||||
PyErr_Format(PyExc_ValueError,
|
||||
"f_lineno can only be set by a trace function");
|
||||
"f_lineno can only be set by a"
|
||||
" line trace function");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -122,20 +123,26 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno)
|
|||
new_lineno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Find the bytecode offset for the start of the given line, or the
|
||||
* first code-owning line after it. */
|
||||
PyBytes_AsStringAndSize(f->f_code->co_lnotab, &lnotab, &lnotab_len);
|
||||
addr = 0;
|
||||
line = f->f_code->co_firstlineno;
|
||||
new_lasti = -1;
|
||||
for (offset = 0; offset < lnotab_len; offset += 2) {
|
||||
addr += lnotab[offset];
|
||||
line += lnotab[offset+1];
|
||||
if (line >= new_lineno) {
|
||||
new_lasti = addr;
|
||||
new_lineno = line;
|
||||
break;
|
||||
else if (new_lineno == f->f_code->co_firstlineno) {
|
||||
new_lasti = 0;
|
||||
new_lineno = f->f_code->co_firstlineno;
|
||||
}
|
||||
else {
|
||||
/* Find the bytecode offset for the start of the given
|
||||
* line, or the first code-owning line after it. */
|
||||
PyBytes_AsStringAndSize(f->f_code->co_lnotab,
|
||||
&lnotab, &lnotab_len);
|
||||
addr = 0;
|
||||
line = f->f_code->co_firstlineno;
|
||||
new_lasti = -1;
|
||||
for (offset = 0; offset < lnotab_len; offset += 2) {
|
||||
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