[pypy-svn] r74360 - in pypy/trunk/pypy/module/cpyext: . test

afa at codespeak.net afa at codespeak.net
Tue May 4 16:34:36 CEST 2010


Author: afa
Date: Tue May  4 16:34:34 2010
New Revision: 74360

Modified:
   pypy/trunk/pypy/module/cpyext/api.py
   pypy/trunk/pypy/module/cpyext/pyerrors.py
   pypy/trunk/pypy/module/cpyext/state.py
   pypy/trunk/pypy/module/cpyext/test/test_api.py
   pypy/trunk/pypy/module/cpyext/test/test_pyerrors.py
Log:
Store an OperationError instead of the (exc_type, exc_value) attributes pair.
This is a little faster when errors are passed from C to pypy and vice-versa,
and it will be easier to add the traceback.


Modified: pypy/trunk/pypy/module/cpyext/api.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/api.py	(original)
+++ pypy/trunk/pypy/module/cpyext/api.py	Tue May  4 16:34:34 2010
@@ -210,8 +210,7 @@
                         if not hasattr(api_function, "error_value"):
                             raise
                         state = space.fromcache(State)
-                        e.normalize_exception(space)
-                        state.set_exception(e.w_type, e.get_w_value(space))
+                        state.set_exception(e)
                         if restype is PyObject:
                             return None
                         else:
@@ -426,11 +425,11 @@
                     print >>sys.stderr, " DONE"
             except OperationError, e:
                 failed = True
-                e.normalize_exception(space)
-                state.set_exception(e.w_type, e.get_w_value(space))
+                state.set_exception(e)
             except BaseException, e:
                 failed = True
-                state.set_exception(space.w_SystemError, space.wrap(str(e)))
+                state.set_exception(OperationError(space.w_SystemError,
+                                                   space.wrap(str(e))))
                 if not we_are_translated():
                     import traceback
                     traceback.print_exc()

Modified: pypy/trunk/pypy/module/cpyext/pyerrors.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/pyerrors.py	(original)
+++ pypy/trunk/pypy/module/cpyext/pyerrors.py	Tue May  4 16:34:34 2010
@@ -14,7 +14,7 @@
     """This function is similar to PyErr_SetString() but lets you specify an
     arbitrary Python object for the "value" of the exception."""
     state = space.fromcache(State)
-    state.set_exception(w_type, w_value)
+    state.set_exception(OperationError(w_type, w_value))
 
 @cpython_api([PyObject, CONST_STRING], lltype.Void)
 def PyErr_SetString(space, w_type, message_ptr):
@@ -29,8 +29,10 @@
 @cpython_api([], PyObject, borrowed=True)
 def PyErr_Occurred(space):
     state = space.fromcache(State)
+    if state.operror is None:
+        return None
     register_container(space, lltype.nullptr(PyObject.TO))
-    return state.exc_type
+    return state.operror.w_type
 
 @cpython_api([], lltype.Void)
 def PyErr_Clear(space):
@@ -47,10 +49,13 @@
     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
+    operror = state.clear_exception()
+    if operror:
+        ptype[0] = make_ref(space, operror.w_type)
+        pvalue[0] = make_ref(space, operror.get_w_value(space))
+    else:
+        ptype[0] = lltype.nullptr(PyObject.TO)
+        pvalue[0] = lltype.nullptr(PyObject.TO)
     ptraceback[0] = lltype.nullptr(PyObject.TO)
 
 @cpython_api([PyObject, PyObject, PyObject], lltype.Void)
@@ -69,8 +74,7 @@
     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
+    state.set_exception(OperationError(w_type, w_value))
     Py_DecRef(space, w_type)
     Py_DecRef(space, w_value)
 

Modified: pypy/trunk/pypy/module/cpyext/state.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/state.py	(original)
+++ pypy/trunk/pypy/module/cpyext/state.py	Tue May  4 16:34:34 2010
@@ -18,8 +18,7 @@
         self.borrowed_objects = {} # { addr of containee -> None }
         self.non_heaptypes = [] # list of wrapped objects
         self.last_container = 0 # addr of last container
-        self.exc_type = None
-        self.exc_value = None
+        self.operror = None
         self.new_method_def = lltype.nullptr(PyMethodDef)
 
         # When importing a package, use this to keep track of its name.  This is
@@ -43,31 +42,32 @@
             ptr = rffi.cast(ADDR, obj)
             self.py_objects_r2w[ptr] = w_obj
 
-    def set_exception(self, w_type, w_value):
+    def set_exception(self, operror):
         self.clear_exception()
-        self.exc_type = w_type
-        self.exc_value = w_value
+        self.operror = operror
 
     def clear_exception(self):
+        """Clear the current exception state, and return the operror.
+        Also frees the borrowed reference returned by PyErr_Occurred()
+        """
         from pypy.module.cpyext.pyobject import Py_DecRef, make_ref
         from pypy.module.cpyext.api import ADDR
         # handling of borrowed objects, remove when we have
         # a weakkeydict
-        exc_type = make_ref(self.space, self.exc_type, borrowed=True)
-        if exc_type:
+        operror = self.operror
+        if operror is not None:
+            exc_type = make_ref(self.space, operror.w_type, borrowed=True)
             Py_DecRef(self.space, exc_type)
             containee_ptr = rffi.cast(ADDR, exc_type)
             del self.borrowed_objects[containee_ptr]
-        self.exc_type = None
-        self.exc_value = None
+        self.operror = None
+        return operror
 
     def check_and_raise_exception(self, always=False):
-        exc_value = self.exc_value
-        exc_type = self.exc_type
-        if exc_type is not None or exc_value is not None:
+        operror = self.operror
+        if operror:
             self.clear_exception()
-            op_err = OperationError(exc_type, exc_value)
-            raise op_err
+            raise operror
         if always:
             raise OperationError(self.space.w_SystemError, self.space.wrap(
                 "Function returned an error result without setting an exception"))

Modified: pypy/trunk/pypy/module/cpyext/test/test_api.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/test/test_api.py	(original)
+++ pypy/trunk/pypy/module/cpyext/test/test_api.py	Tue May  4 16:34:34 2010
@@ -30,10 +30,10 @@
             raise Exception("%s is not callable" % (f,))
         f(*args)
         state = space.fromcache(State)
-        tp = state.exc_type
-        if not tp:
+        operror = state.operror
+        if not operror:
             raise Exception("DID NOT RAISE")
-        if getattr(space, 'w_' + expected_exc.__name__) is not tp:
+        if getattr(space, 'w_' + expected_exc.__name__) is not operror.w_type:
             raise Exception("Wrong exception")
         state.clear_exception()
 

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	Tue May  4 16:34:34 2010
@@ -50,25 +50,26 @@
         api.PyErr_SetObject(space.w_ValueError, space.wrap("a value"))
         assert api.PyErr_Occurred() is space.w_ValueError
         state = space.fromcache(State)
-        assert space.eq_w(state.exc_value, space.wrap("a value"))
+        assert space.eq_w(state.operror.get_w_value(space),
+                          space.wrap("a value"))
 
         api.PyErr_Clear()
 
     def test_SetNone(self, space, api):
         api.PyErr_SetNone(space.w_KeyError)
         state = space.fromcache(State)
-        assert space.eq_w(state.exc_type, space.w_KeyError)
-        assert space.eq_w(state.exc_value, space.w_None)
+        assert space.eq_w(state.operror.w_type, space.w_KeyError)
+        assert space.eq_w(state.operror.get_w_value(space), space.w_None)
         api.PyErr_Clear()
 
         api.PyErr_NoMemory()
-        assert space.eq_w(state.exc_type, space.w_MemoryError)
+        assert space.eq_w(state.operror.w_type, space.w_MemoryError)
         api.PyErr_Clear()
         
     def test_BadArgument(self, space, api):
         api.PyErr_BadArgument()
         state = space.fromcache(State)
-        assert space.eq_w(state.exc_type, space.w_TypeError)
+        assert space.eq_w(state.operror.w_type, space.w_TypeError)
         api.PyErr_Clear()
 
 class AppTestFetch(AppTestCpythonExtensionBase):
@@ -92,7 +93,7 @@
              '''
              ),
             ])
-        module.check_error()
+        assert module.check_error()
 
     def test_fetch_and_restore(self):
         module = self.import_extension('foo', [
@@ -106,8 +107,6 @@
                  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;
@@ -116,7 +115,7 @@
              '''
              ),
             ])
-        module.check_error()
+        assert 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