[pypy-svn] r79794 - in pypy/trunk/pypy/module/cpyext: . test
afa at codespeak.net
afa at codespeak.net
Fri Dec 3 22:52:53 CET 2010
Author: afa
Date: Fri Dec 3 22:52:49 2010
New Revision: 79794
Modified:
pypy/trunk/pypy/module/cpyext/pyerrors.py
pypy/trunk/pypy/module/cpyext/stubs.py
pypy/trunk/pypy/module/cpyext/test/test_pyerrors.py
Log:
Implement PyErr_NormalizeException()
Modified: pypy/trunk/pypy/module/cpyext/pyerrors.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/pyerrors.py (original)
+++ pypy/trunk/pypy/module/cpyext/pyerrors.py Fri Dec 3 22:52:49 2010
@@ -5,7 +5,7 @@
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, PyObjectP, make_ref, Py_DecRef, borrow_from)
+ PyObject, PyObjectP, make_ref, from_ref, Py_DecRef, borrow_from)
from pypy.module.cpyext.state import State
from pypy.module.cpyext.import_ import PyImport_Import
from pypy.rlib.rposix import get_errno
@@ -80,6 +80,21 @@
Py_DecRef(space, w_value)
Py_DecRef(space, w_traceback)
+ at cpython_api([PyObjectP, PyObjectP, PyObjectP], lltype.Void)
+def PyErr_NormalizeException(space, exc_p, val_p, tb_p):
+ """Under certain circumstances, the values returned by PyErr_Fetch() below
+ can be "unnormalized", meaning that *exc is a class object but *val is
+ not an instance of the same class. This function can be used to instantiate
+ the class in that case. If the values are already normalized, nothing happens.
+ The delayed normalization is implemented to improve performance."""
+ operr = OperationError(from_ref(space, exc_p[0]),
+ from_ref(space, val_p[0]))
+ operr.normalize_exception(space)
+ Py_DecRef(space, exc_p[0])
+ Py_DecRef(space, val_p[0])
+ exc_p[0] = make_ref(space, operr.w_type)
+ val_p[0] = make_ref(space, operr.get_w_value(space))
+
@cpython_api([], lltype.Void)
def PyErr_BadArgument(space):
"""This is a shorthand for PyErr_SetString(PyExc_TypeError, message), where
Modified: pypy/trunk/pypy/module/cpyext/stubs.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/stubs.py (original)
+++ pypy/trunk/pypy/module/cpyext/stubs.py Fri Dec 3 22:52:49 2010
@@ -668,15 +668,6 @@
"""
raise NotImplementedError
- at cpython_api([PyObjectP, PyObjectP, PyObjectP], lltype.Void)
-def PyErr_NormalizeException(space, exc, val, tb):
- """Under certain circumstances, the values returned by PyErr_Fetch() below
- can be "unnormalized", meaning that *exc is a class object but *val is
- not an instance of the same class. This function can be used to instantiate
- the class in that case. If the values are already normalized, nothing happens.
- The delayed normalization is implemented to improve performance."""
- raise NotImplementedError
-
@cpython_api([PyObject, rffi.CCHARP], PyObject)
def PyErr_SetFromErrnoWithFilename(space, type, filename):
"""Similar to PyErr_SetFromErrno(), with the additional behavior that if
Modified: pypy/trunk/pypy/module/cpyext/test/test_pyerrors.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/test/test_pyerrors.py (original)
+++ pypy/trunk/pypy/module/cpyext/test/test_pyerrors.py Fri Dec 3 22:52:49 2010
@@ -129,6 +129,42 @@
])
assert module.check_error()
+
+ def test_normalize(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 (type != PyExc_TypeError)
+ Py_RETURN_FALSE;
+ if (!PyString_Check(val))
+ Py_RETURN_FALSE;
+ /* Normalize */
+ PyErr_NormalizeException(&type, &val, &tb);
+ if (type != PyExc_TypeError)
+ Py_RETURN_FALSE;
+ if (val->ob_type != PyExc_TypeError)
+ Py_RETURN_FALSE;
+
+ /* Normalize again */
+ PyErr_NormalizeException(&type, &val, &tb);
+ if (type != PyExc_TypeError)
+ Py_RETURN_FALSE;
+ if (val->ob_type != PyExc_TypeError)
+ Py_RETURN_FALSE;
+
+ PyErr_Restore(type, val, tb);
+ if (!PyErr_Occurred())
+ Py_RETURN_FALSE;
+ Py_RETURN_TRUE;
+ '''
+ ),
+ ])
+ assert module.check_error()
+
def test_SetFromErrno(self):
import sys
if sys.platform != 'win32':
More information about the Pypy-commit
mailing list