Author: Maciej Fijalkowski <[email protected]>
Branch:
Changeset: r80203:ab8cc1414237
Date: 2015-10-14 13:47 +0200
http://bitbucket.org/pypy/pypy/changeset/ab8cc1414237/
Log: Merged in devin.jeanpierre/pypy-cpyext-traceback (pull request #335)
Improve traceback support in cpyext.
diff --git a/pypy/module/cpyext/__init__.py b/pypy/module/cpyext/__init__.py
--- a/pypy/module/cpyext/__init__.py
+++ b/pypy/module/cpyext/__init__.py
@@ -66,6 +66,7 @@
import pypy.module.cpyext.codecs
import pypy.module.cpyext.pyfile
import pypy.module.cpyext.pystrtod
+import pypy.module.cpyext.pytraceback
# now that all rffi_platform.Struct types are registered, configure them
api.configure_types()
diff --git a/pypy/module/cpyext/include/Python.h
b/pypy/module/cpyext/include/Python.h
--- a/pypy/module/cpyext/include/Python.h
+++ b/pypy/module/cpyext/include/Python.h
@@ -126,6 +126,7 @@
#include "fileobject.h"
#include "pysignals.h"
#include "pythread.h"
+#include "traceback.h"
/* Missing definitions */
#include "missing.h"
diff --git a/pypy/module/cpyext/include/frameobject.h
b/pypy/module/cpyext/include/frameobject.h
--- a/pypy/module/cpyext/include/frameobject.h
+++ b/pypy/module/cpyext/include/frameobject.h
@@ -4,7 +4,7 @@
extern "C" {
#endif
-typedef struct {
+typedef struct _frame {
PyObject_HEAD
PyCodeObject *f_code;
PyObject *f_globals;
diff --git a/pypy/module/cpyext/include/traceback.h
b/pypy/module/cpyext/include/traceback.h
--- a/pypy/module/cpyext/include/traceback.h
+++ b/pypy/module/cpyext/include/traceback.h
@@ -4,7 +4,15 @@
extern "C" {
#endif
-typedef PyObject PyTracebackObject;
+struct _frame;
+
+typedef struct _traceback {
+ PyObject_HEAD
+ struct _traceback *tb_next;
+ struct _frame *tb_frame;
+ int tb_lasti;
+ int tb_lineno;
+} PyTracebackObject;
#ifdef __cplusplus
}
diff --git a/pypy/module/cpyext/pytraceback.py
b/pypy/module/cpyext/pytraceback.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/pytraceback.py
@@ -0,0 +1,50 @@
+from rpython.rtyper.lltypesystem import rffi, lltype
+from pypy.module.cpyext.api import (
+ PyObjectFields, generic_cpy_call, CONST_STRING, CANNOT_FAIL, Py_ssize_t,
+ cpython_api, bootstrap_function, cpython_struct, build_type_checkers)
+from pypy.module.cpyext.pyobject import (
+ PyObject, make_ref, from_ref, Py_DecRef, make_typedescr, borrow_from)
+from pypy.module.cpyext.frameobject import PyFrameObject
+from rpython.rlib.unroll import unrolling_iterable
+from pypy.interpreter.error import OperationError
+from pypy.interpreter.pytraceback import PyTraceback
+from pypy.interpreter import pycode
+
+
+PyTracebackObjectStruct = lltype.ForwardReference()
+PyTracebackObject = lltype.Ptr(PyTracebackObjectStruct)
+PyTracebackObjectFields = PyObjectFields + (
+ ("tb_next", PyTracebackObject),
+ ("tb_frame", PyFrameObject),
+ ("tb_lasti", rffi.INT),
+ ("tb_lineno", rffi.INT),
+)
+cpython_struct("PyTracebackObject", PyTracebackObjectFields,
PyTracebackObjectStruct)
+
+@bootstrap_function
+def init_traceback(space):
+ make_typedescr(PyTraceback.typedef,
+ basestruct=PyTracebackObject.TO,
+ attach=traceback_attach,
+ dealloc=traceback_dealloc)
+
+
+def traceback_attach(space, py_obj, w_obj):
+ py_traceback = rffi.cast(PyTracebackObject, py_obj)
+ traceback = space.interp_w(PyTraceback, w_obj)
+ if traceback.next is None:
+ w_next_traceback = None
+ else:
+ w_next_traceback = space.wrap(traceback.next)
+ py_traceback.c_tb_next = rffi.cast(PyTracebackObject, make_ref(space,
w_next_traceback))
+ py_traceback.c_tb_frame = rffi.cast(PyFrameObject, make_ref(space,
space.wrap(traceback.frame)))
+ rffi.setintfield(py_traceback, 'c_tb_lasti', traceback.lasti)
+ rffi.setintfield(py_traceback, 'c_tb_lineno',traceback.get_lineno())
+
+@cpython_api([PyObject], lltype.Void, external=False)
+def traceback_dealloc(space, py_obj):
+ py_traceback = rffi.cast(PyTracebackObject, py_obj)
+ Py_DecRef(space, rffi.cast(PyObject, py_traceback.c_tb_next))
+ Py_DecRef(space, rffi.cast(PyObject, py_traceback.c_tb_frame))
+ from pypy.module.cpyext.object import PyObject_dealloc
+ PyObject_dealloc(space, py_obj)
diff --git a/pypy/module/cpyext/test/test_traceback.py
b/pypy/module/cpyext/test/test_traceback.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/test/test_traceback.py
@@ -0,0 +1,40 @@
+from rpython.rtyper.lltypesystem import lltype, rffi
+from pypy.module.cpyext.test.test_api import BaseApiTest
+from pypy.module.cpyext.pyobject import PyObject, make_ref, from_ref
+from pypy.module.cpyext.pytraceback import PyTracebackObject
+from pypy.interpreter.pytraceback import PyTraceback
+from pypy.interpreter.pyframe import PyFrame
+
+class TestPyTracebackObject(BaseApiTest):
+ def test_traceback(self, space, api):
+ w_traceback = space.appexec([], """():
+ import sys
+ try:
+ 1/0
+ except:
+ return sys.exc_info()[2]
+ """)
+ py_obj = make_ref(space, w_traceback)
+ py_traceback = rffi.cast(PyTracebackObject, py_obj)
+ assert (from_ref(space, rffi.cast(PyObject, py_traceback.c_ob_type)) is
+ space.gettypeobject(PyTraceback.typedef))
+
+ traceback = space.interp_w(PyTraceback, w_traceback)
+ assert traceback.lasti == py_traceback.c_tb_lasti
+ assert traceback.get_lineno() == py_traceback.c_tb_lineno
+ assert space.eq_w(space.getattr(w_traceback, space.wrap("tb_lasti")),
+ space.wrap(py_traceback.c_tb_lasti))
+ assert space.is_w(space.getattr(w_traceback, space.wrap("tb_frame")),
+ from_ref(space, rffi.cast(PyObject,
+ py_traceback.c_tb_frame)))
+
+ while not space.is_w(w_traceback, space.w_None):
+ assert space.is_w(
+ w_traceback,
+ from_ref(space, rffi.cast(PyObject, py_traceback)))
+ w_traceback = space.getattr(w_traceback, space.wrap("tb_next"))
+ py_traceback = py_traceback.c_tb_next
+
+ assert lltype.normalizeptr(py_traceback) is None
+
+ api.Py_DecRef(py_obj)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit