Commit 17e63f6a authored by Dmitry Trofimov's avatar Dmitry Trofimov

Fix tests after handling the case when tracing function returns None

parent dfc47cd4
...@@ -198,7 +198,8 @@ ...@@ -198,7 +198,8 @@
PyThreadState *tstate; \ PyThreadState *tstate; \
PyGILState_STATE state = PyGILState_Ensure(); \ PyGILState_STATE state = PyGILState_Ensure(); \
tstate = PyThreadState_GET(); \ tstate = PyThreadState_GET(); \
if (unlikely(tstate->use_tracing && __pyx_frame->f_trace != Py_None)) { \ if (unlikely(tstate->use_tracing && tstate->c_tracefunc \
&& __pyx_frame->f_trace != Py_None)) { \
ret = __Pyx_call_line_trace_func(tstate, $frame_cname, lineno); \ ret = __Pyx_call_line_trace_func(tstate, $frame_cname, lineno); \
} \ } \
PyGILState_Release(state); \ PyGILState_Release(state); \
...@@ -206,7 +207,8 @@ ...@@ -206,7 +207,8 @@
} \ } \
} else { \ } else { \
PyThreadState* tstate = PyThreadState_GET(); \ PyThreadState* tstate = PyThreadState_GET(); \
if (unlikely(tstate->use_tracing && __pyx_frame->f_trace != Py_None)) { \ if (unlikely(tstate->use_tracing && tstate->c_tracefunc \
&& __pyx_frame->f_trace != Py_None)) { \
int ret = __Pyx_call_line_trace_func(tstate, $frame_cname, lineno); \ int ret = __Pyx_call_line_trace_func(tstate, $frame_cname, lineno); \
if (unlikely(ret)) goto_error; \ if (unlikely(ret)) goto_error; \
} \ } \
...@@ -216,7 +218,8 @@ ...@@ -216,7 +218,8 @@
#define __Pyx_TraceLine(lineno, nogil, goto_error) \ #define __Pyx_TraceLine(lineno, nogil, goto_error) \
if (likely(!__Pyx_use_tracing)); else { \ if (likely(!__Pyx_use_tracing)); else { \
PyThreadState* tstate = PyThreadState_GET(); \ PyThreadState* tstate = PyThreadState_GET(); \
if (unlikely(tstate->use_tracing && __pyx_frame->f_trace != Py_None)) { \ if (unlikely(tstate->use_tracing && tstate->c_tracefunc \
&& __pyx_frame->f_trace != Py_None)) { \
int ret = __Pyx_call_line_trace_func(tstate, $frame_cname, lineno); \ int ret = __Pyx_call_line_trace_func(tstate, $frame_cname, lineno); \
if (unlikely(ret)) goto_error; \ if (unlikely(ret)) goto_error; \
} \ } \
......
...@@ -30,25 +30,62 @@ map_trace_types = { ...@@ -30,25 +30,62 @@ map_trace_types = {
}.get }.get
cdef int _trace_func(PyObject* _traceobj, PyFrameObject* _frame, int what, PyObject* arg) except -1: cdef int trace_trampoline(PyObject* _traceobj, PyFrameObject* _frame, int what, PyObject* _arg) except -1:
frame, traceobj = <object>_frame, <object>_traceobj frame = <object>_frame
traceobj.append((map_trace_types(what), frame.f_lineno - frame.f_code.co_firstlineno)) traceobj = <object>_traceobj if _traceobj else None
return 0 arg = <object>_arg if _arg else None
cdef int _failing_call_trace_func(PyObject* _traceobj, PyFrameObject* _frame, int what, PyObject* arg) except -1:
if what == PyTrace_CALL: if what == PyTrace_CALL:
raise ValueError("failing call trace!") callback = traceobj
return _trace_func(_traceobj, _frame, what, arg) else:
callback = frame.f_trace
if callback is None:
return 0
result = callback(frame, what, arg)
frame.f_trace = result
if result is None:
PyEval_SetTrace(NULL, None)
return -1
else:
return 0
def _create_trace_func(trace):
def _trace_func(frame, event, arg):
trace.append((map_trace_types(event), frame.f_lineno -
frame.f_code.co_firstlineno))
return _trace_func
return _trace_func
def _create_failing_call_trace_func(trace):
func = _create_trace_func(trace)
def _trace_func(frame, event, arg):
if event == PyTrace_CALL:
raise ValueError("failing call trace!")
func(frame, event, arg)
return _trace_func
return _trace_func
def _create__failing_line_trace_func(trace):
func = _create_trace_func(trace)
def _trace_func(frame, event, arg):
if event == PyTrace_LINE and trace:
if trace and trace[0] == frame.f_code.co_name:
# first line in the right function => fail!
raise ValueError("failing line trace!")
cdef int _failing_line_trace_func(PyObject* _traceobj, PyFrameObject* _frame, int what, PyObject* arg) except -1: func(frame, event, arg)
if what == PyTrace_LINE and _traceobj: return _trace_func
frame, traceobj = <object>_frame, <object>_traceobj return _trace_func
if traceobj and traceobj[0] == frame.f_code.co_name:
# first line in the right function => fail!
raise ValueError("failing line trace!")
return _trace_func(_traceobj, _frame, what, arg)
def cy_add(a,b): def cy_add(a,b):
...@@ -87,7 +124,7 @@ def run_trace(func, *args): ...@@ -87,7 +124,7 @@ def run_trace(func, *args):
[('line', 2), ('line', 5), ('return', 5)] [('line', 2), ('line', 5), ('return', 5)]
""" """
trace = [] trace = []
PyEval_SetTrace(<Py_tracefunc>_trace_func, trace) PyEval_SetTrace(<Py_tracefunc>trace_trampoline, _create_trace_func(trace))
try: try:
func(*args) func(*args)
finally: finally:
...@@ -105,7 +142,7 @@ def fail_on_call_trace(func, *args): ...@@ -105,7 +142,7 @@ def fail_on_call_trace(func, *args):
ValueError: failing call trace! ValueError: failing call trace!
""" """
trace = [] trace = []
PyEval_SetTrace(<Py_tracefunc>_failing_call_trace_func, trace) PyEval_SetTrace(<Py_tracefunc>trace_trampoline, _create_failing_call_trace_func(trace))
try: try:
func(*args) func(*args)
finally: finally:
...@@ -142,7 +179,7 @@ def fail_on_line_trace(fail_func): ...@@ -142,7 +179,7 @@ def fail_on_line_trace(fail_func):
cdef int x = 1 cdef int x = 1
trace = ['NO ERROR'] trace = ['NO ERROR']
exception = None exception = None
PyEval_SetTrace(<Py_tracefunc>_failing_line_trace_func, trace) PyEval_SetTrace(<Py_tracefunc>trace_trampoline, _create__failing_line_trace_func(trace))
try: try:
x += 1 x += 1
cy_add(1, 2) cy_add(1, 2)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment