[pypy-svn] r73992 - in pypy/branch/cpython-extension/pypy/module/cpyext: . test
afa at codespeak.net
afa at codespeak.net
Thu Apr 22 20:42:30 CEST 2010
Author: afa
Date: Thu Apr 22 20:42:28 2010
New Revision: 73992
Modified:
pypy/branch/cpython-extension/pypy/module/cpyext/pyerrors.py
pypy/branch/cpython-extension/pypy/module/cpyext/pyobject.py
pypy/branch/cpython-extension/pypy/module/cpyext/test/test_pyerrors.py
Log:
PyErr_Fetch and PyErr_Restore
Modified: pypy/branch/cpython-extension/pypy/module/cpyext/pyerrors.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/module/cpyext/pyerrors.py (original)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/pyerrors.py Thu Apr 22 20:42:28 2010
@@ -4,7 +4,8 @@
from pypy.interpreter.error import OperationError
from pypy.module.cpyext.api import cpython_api, CANNOT_FAIL, CONST_STRING
from pypy.module.exceptions.interp_exceptions import W_RuntimeWarning
-from pypy.module.cpyext.pyobject import PyObject, make_ref, register_container
+from pypy.module.cpyext.pyobject import (
+ PyObject, PyObjectP, make_ref, Py_DecRef, register_container)
from pypy.module.cpyext.state import State
from pypy.rlib.rposix import get_errno
@@ -60,6 +61,43 @@
state = space.fromcache(State)
state.clear_exception()
+ at cpython_api([PyObjectP, PyObjectP, PyObjectP], lltype.Void)
+def PyErr_Fetch(space, ptype, pvalue, ptraceback):
+ """Retrieve the error indicator into three variables whose addresses are passed.
+ If the error indicator is not set, set all three variables to NULL. If it is
+ set, it will be cleared and you own a reference to each object retrieved. The
+ value and traceback object may be NULL even when the type object is not.
+
+ This function is normally only used by code that needs to handle exceptions or
+ by code that needs to save and restore the error indicator temporarily."""
+ state = space.fromcache(State)
+ ptype[0] = make_ref(space, state.exc_type, steal=True)
+ pvalue[0] = make_ref(space, state.exc_type, steal=True)
+ state.exc_type = None
+ state.exc_value = None
+ ptraceback[0] = lltype.nullptr(PyObject.TO)
+
+ at cpython_api([PyObject, PyObject, PyObject], lltype.Void)
+def PyErr_Restore(space, w_type, w_value, w_traceback):
+ """Set the error indicator from the three objects. If the error indicator is
+ already set, it is cleared first. If the objects are NULL, the error
+ indicator is cleared. Do not pass a NULL type and non-NULL value or
+ traceback. The exception type should be a class. Do not pass an invalid
+ exception type or value. (Violating these rules will cause subtle problems
+ later.) This call takes away a reference to each object: you must own a
+ reference to each object before the call and after the call you no longer own
+ these references. (If you don't understand this, don't use this function. I
+ warned you.)
+
+ This function is normally only used by code that needs to save and restore the
+ error indicator temporarily; use PyErr_Fetch() to save the current
+ exception state."""
+ state = space.fromcache(State)
+ state.exc_type = w_type
+ state.exc_value = w_value
+ Py_DecRef(space, w_type)
+ Py_DecRef(space, w_value)
+
@cpython_api([], lltype.Void)
def PyErr_BadInternalCall(space):
raise OperationError(space.w_SystemError, space.wrap("Bad internal call!"))
Modified: pypy/branch/cpython-extension/pypy/module/cpyext/pyobject.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/module/cpyext/pyobject.py (original)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/pyobject.py Thu Apr 22 20:42:28 2010
@@ -3,7 +3,7 @@
from pypy.interpreter.baseobjspace import W_Root, SpaceCache
from pypy.rpython.lltypesystem import rffi, lltype
from pypy.module.cpyext.api import cpython_api, bootstrap_function, \
- PyObject, ADDR,\
+ PyObject, PyObjectP, ADDR,\
Py_TPFLAGS_HEAPTYPE, PyTypeObjectPtr
from pypy.module.cpyext.state import State
from pypy.objspace.std.typeobject import W_TypeObject
Modified: pypy/branch/cpython-extension/pypy/module/cpyext/test/test_pyerrors.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/module/cpyext/test/test_pyerrors.py (original)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/test/test_pyerrors.py Thu Apr 22 20:42:28 2010
@@ -94,6 +94,29 @@
])
module.check_error()
+ def test_fetch_and_restore(self):
+ module = self.import_extension('foo', [
+ ("check_error", "METH_NOARGS",
+ '''
+ PyObject *type, *val, *tb;
+ PyErr_SetString(PyExc_TypeError, "message");
+
+ PyErr_Fetch(&type, &val, &tb);
+ if (PyErr_Occurred())
+ return NULL;
+ if (type != PyExc_TypeError)
+ Py_RETURN_FALSE;
+ if (val->ob_type != type)
+ Py_RETURN_FALSE;
+ PyErr_Restore(type, val, tb);
+ if (!PyErr_Occurred())
+ Py_RETURN_FALSE;
+ PyErr_Clear();
+ Py_RETURN_TRUE;
+ '''
+ ),
+ ])
+ module.check_error()
def test_SetFromErrno(self):
skip("The test does not set the errno in a way which "
More information about the Pypy-commit
mailing list