[pypy-commit] pypy default: Expose traceback fields in cpyext, and expose PyFrameObject as "struct _frame".
devin.jeanpierre
noreply at buildbot.pypy.org
Wed Oct 14 07:47:47 EDT 2015
Author: Devin Jeanpierre <jeanpierreda at gmail.com>
Branch:
Changeset: r80197:6e335c196a45
Date: 2015-10-04 23:35 -0700
http://bitbucket.org/pypy/pypy/changeset/6e335c196a45/
Log: Expose traceback fields in cpyext, and expose PyFrameObject as
"struct _frame".
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,47 @@
+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)
+
+ at bootstrap_function
+def init_traceback(space):
+ make_typedescr(PyTraceback.typedef,
+ basestruct=PyTracebackObject.TO,
+ attach=traceback_attach,
+ dealloc=traceback_dealloc)
+ # TODO: decref tb_frame properly!
+
+
+def traceback_attach(space, py_obj, w_obj):
+ py_traceback = rffi.cast(PyTracebackObject, py_obj)
+ traceback = space.interp_w(PyTraceback, w_obj)
+ py_traceback.c_tb_next = rffi.cast(PyTracebackObject, make_ref(space, space.wrap(traceback.next)))
+ 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())
+
+ at 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,28 @@
+from rpython.rtyper.lltypesystem import 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 traceback.next is space.interp_w(PyTraceback, from_ref(space, rffi.cast(PyObject, py_traceback.c_tb_next)), can_be_None=True)
+ assert traceback.frame is space.interp_w(PyFrame, from_ref(space, rffi.cast(PyObject, py_traceback.c_tb_frame)), can_be_None=True)
+
+ api.Py_DecRef(py_obj)
More information about the pypy-commit
mailing list