[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