Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 76 additions & 0 deletions Lib/test/test_sys_settrace.py
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,82 @@ def func():
(7, 'line'),
(7, 'return')])

def test_20_async_for_loop(self):
class AsyncIteratorWrapper:
def __init__(self, obj):
self._it = iter(obj)

def __aiter__(self):
return self

async def __anext__(self):
try:
return next(self._it)
except StopIteration:
raise StopAsyncIteration

async def doit_async():
async for letter in AsyncIteratorWrapper("abc"):
x = letter
y = 42

def run(tracer):
x = doit_async()
try:
sys.settrace(tracer)
x.send(None)
finally:
sys.settrace(None)

tracer = self.make_tracer()
events = [
(0, 'call'),
(1, 'line'),
(-12, 'call'),
(-11, 'line'),
(-11, 'return'),
(-9, 'call'),
(-8, 'line'),
(-8, 'return'),
(-6, 'call'),
(-5, 'line'),
(-4, 'line'),
(-4, 'return'),
(1, 'exception'),
(2, 'line'),
(1, 'line'),
(-6, 'call'),
(-5, 'line'),
(-4, 'line'),
(-4, 'return'),
(1, 'exception'),
(2, 'line'),
(1, 'line'),
(-6, 'call'),
(-5, 'line'),
(-4, 'line'),
(-4, 'return'),
(1, 'exception'),
(2, 'line'),
(1, 'line'),
(-6, 'call'),
(-5, 'line'),
(-4, 'line'),
(-4, 'exception'),
(-3, 'line'),
(-2, 'line'),
(-2, 'exception'),
(-2, 'return'),
(1, 'exception'),
(3, 'line'),
(3, 'return')]
try:
run(tracer.trace)
except Exception:
pass
self.compare_events(doit_async.__code__.co_firstlineno,
tracer.events, events)


class SkipLineEventsTraceTestCase(TraceTestCase):
"""Repeat the trace tests, but with per-line events skipped"""
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix incorrect line execution reporting in trace functions when tracing the
last iteration of asynchronous for loops. Patch by Pablo Galindo.
14 changes: 9 additions & 5 deletions Python/ceval.c
Original file line number Diff line number Diff line change
Expand Up @@ -3610,11 +3610,15 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
PUSH(val);
PUSH(exc);
JUMPTO(handler);
if (_Py_TracingPossible(ceval) &&
((f->f_lasti < instr_lb || f->f_lasti >= instr_ub) ||
!(f->f_lasti == instr_lb || f->f_lasti < instr_prev))) {
/* Make sure that we trace line after exception */
instr_prev = INT_MAX;
if (_Py_TracingPossible(ceval)) {
int needs_new_execution_window = (f->f_lasti < instr_lb || f->f_lasti >= instr_ub);
int needs_line_update = (f->f_lasti == instr_lb || f->f_lasti < instr_prev);
/* Make sure that we trace line after exception if we are in a new execution
* window or we don't need a line update and we are not in the first instruction
* of the line. */
if (needs_new_execution_window || (!needs_line_update && instr_lb > 0)) {
instr_prev = INT_MAX;
}
}
/* Resume normal execution */
goto main_loop;
Expand Down