Commit 40370f54 authored by Robert Bradshaw's avatar Robert Bradshaw Committed by GitHub

Merge pull request #1719 from robertwb/tracebaoks

Make C lines in exception tracebacks a runtime setting.
parents bdcc37cd 7af30ae2
...@@ -24,6 +24,10 @@ Features added ...@@ -24,6 +24,10 @@ Features added
* cdef classes now support pickling by default when possible. * cdef classes now support pickling by default when possible.
* The display of C lines in Cython tracebacks is now settable at runtime
via `import cython_runtime; cython_runtime.cline_in_traceback=True`.
The default has been changed to False.
Bugs fixed Bugs fixed
---------- ----------
......
...@@ -702,6 +702,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -702,6 +702,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln('static PyObject *%s;' % env.module_cname) code.putln('static PyObject *%s;' % env.module_cname)
code.putln('static PyObject *%s;' % env.module_dict_cname) code.putln('static PyObject *%s;' % env.module_dict_cname)
code.putln('static PyObject *%s;' % Naming.builtins_cname) code.putln('static PyObject *%s;' % Naming.builtins_cname)
code.putln('static PyObject *%s;' % Naming.cython_runtime_cname)
code.putln('static PyObject *%s;' % Naming.empty_tuple) code.putln('static PyObject *%s;' % Naming.empty_tuple)
code.putln('static PyObject *%s;' % Naming.empty_bytes) code.putln('static PyObject *%s;' % Naming.empty_bytes)
code.putln('static PyObject *%s;' % Naming.empty_unicode) code.putln('static PyObject *%s;' % Naming.empty_unicode)
...@@ -2476,6 +2477,10 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -2476,6 +2477,10 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
'%s = PyImport_AddModule(__Pyx_BUILTIN_MODULE_NAME); %s' % ( '%s = PyImport_AddModule(__Pyx_BUILTIN_MODULE_NAME); %s' % (
Naming.builtins_cname, Naming.builtins_cname,
code.error_goto_if_null(Naming.builtins_cname, self.pos))) code.error_goto_if_null(Naming.builtins_cname, self.pos)))
code.putln(
'%s = PyImport_AddModule((char *) "cython_runtime"); %s' % (
Naming.cython_runtime_cname,
code.error_goto_if_null(Naming.cython_runtime_cname, self.pos)))
code.putln('#if CYTHON_COMPILING_IN_PYPY') code.putln('#if CYTHON_COMPILING_IN_PYPY')
code.putln('Py_INCREF(%s);' % Naming.builtins_cname) code.putln('Py_INCREF(%s);' % Naming.builtins_cname)
code.putln('#endif') code.putln('#endif')
......
...@@ -112,6 +112,7 @@ frame_code_cname = pyrex_prefix + "frame_code" ...@@ -112,6 +112,7 @@ frame_code_cname = pyrex_prefix + "frame_code"
binding_cfunc = pyrex_prefix + "binding_PyCFunctionType" binding_cfunc = pyrex_prefix + "binding_PyCFunctionType"
fused_func_prefix = pyrex_prefix + 'fuse_' fused_func_prefix = pyrex_prefix + 'fuse_'
quick_temp_cname = pyrex_prefix + "temp" # temp variable for quick'n'dirty temping quick_temp_cname = pyrex_prefix + "temp" # temp variable for quick'n'dirty temping
cython_runtime_cname = pyrex_prefix + "cython_runtime"
global_code_object_cache_find = pyrex_prefix + 'find_code_object' global_code_object_cache_find = pyrex_prefix + 'find_code_object'
global_code_object_cache_insert = pyrex_prefix + 'insert_code_object' global_code_object_cache_insert = pyrex_prefix + 'insert_code_object'
......
...@@ -600,13 +600,25 @@ static void __Pyx_AddTraceback(const char *funcname, int c_line, ...@@ -600,13 +600,25 @@ static void __Pyx_AddTraceback(const char *funcname, int c_line,
int py_line, const char *filename) { int py_line, const char *filename) {
PyCodeObject *py_code = 0; PyCodeObject *py_code = 0;
PyFrameObject *py_frame = 0; PyFrameObject *py_frame = 0;
PyObject *use_cline = 0;
PyObject *ptype, *pvalue, *ptraceback;
py_code = $global_code_object_cache_find(c_line ? c_line : py_line); if (c_line) {
PyErr_Fetch(&ptype, &pvalue, &ptraceback);
use_cline = PyObject_GetAttrString(${cython_runtime_cname}, "cline_in_traceback");
if (use_cline == NULL || PyObject_Not(use_cline) != 0) {
c_line = 0;
}
PyErr_Restore(ptype, pvalue, ptraceback);
}
// Negate to avoid collisions between py and c lines.
py_code = $global_code_object_cache_find(c_line ? -c_line : py_line);
if (!py_code) { if (!py_code) {
py_code = __Pyx_CreateCodeObjectForTraceback( py_code = __Pyx_CreateCodeObjectForTraceback(
funcname, c_line, py_line, filename); funcname, c_line, py_line, filename);
if (!py_code) goto bad; if (!py_code) goto bad;
$global_code_object_cache_insert(c_line ? c_line : py_line, py_code); $global_code_object_cache_insert(c_line ? -c_line : py_line, py_code);
} }
py_frame = PyFrame_New( py_frame = PyFrame_New(
PyThreadState_GET(), /*PyThreadState *tstate,*/ PyThreadState_GET(), /*PyThreadState *tstate,*/
...@@ -620,4 +632,5 @@ static void __Pyx_AddTraceback(const char *funcname, int c_line, ...@@ -620,4 +632,5 @@ static void __Pyx_AddTraceback(const char *funcname, int c_line,
bad: bad:
Py_XDECREF(py_code); Py_XDECREF(py_code);
Py_XDECREF(py_frame); Py_XDECREF(py_frame);
Py_XDECREF(use_cline);
} }
import traceback
def foo1():
foo2()
cdef foo2():
foo3()
cdef int foo3() except -1:
raise RuntimeError('my_message')
def test_traceback(cline_in_traceback=None):
"""
>>> test_traceback()
>>> test_traceback(True)
>>> test_traceback(False)
"""
if cline_in_traceback is not None:
import cython_runtime
cython_runtime.cline_in_traceback = cline_in_traceback
try:
foo1()
except:
tb_string = traceback.format_exc()
expected = (
'tracebacks.pyx',
'foo1', 'foo2', 'foo3',
'line 4', 'line 7', 'line 10',
'my_message')
for s in expected:
assert s in tb_string, s
if cline_in_traceback:
assert 'tracebacks.c' in tb_string
else:
assert 'tracebacks.c' not in tb_string
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