Author: Amaury Forgeot d'Arc <[email protected]>
Branch: py3k
Changeset: r59095:92a51efa3cff
Date: 2012-11-23 21:46 +0100
http://bitbucket.org/pypy/pypy/changeset/92a51efa3cff/

Log:    cpyext: Implement PyException_* functions.

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
@@ -61,6 +61,7 @@
 import pypy.module.cpyext.funcobject
 import pypy.module.cpyext.frameobject
 import pypy.module.cpyext.pypyintf
+import pypy.module.cpyext.exception
 import pypy.module.cpyext.memoryobject
 import pypy.module.cpyext.codecs
 import pypy.module.cpyext.pyfile
diff --git a/pypy/module/cpyext/exception.py b/pypy/module/cpyext/exception.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/exception.py
@@ -0,0 +1,79 @@
+# Provide implementation of PyException_ functions.
+
+from pypy.module.cpyext.api import cpython_api
+from pypy.module.cpyext.pyobject import PyObject, from_ref, Py_DecRef
+from pypy.rpython.lltypesystem import rffi, lltype
+
+
+@cpython_api([PyObject], PyObject)
+def PyExceptionInstance_Class(space, w_obj):
+    return space.type(w_obj)
+
+
+@cpython_api([PyObject], PyObject)
+def PyException_GetTraceback(space, w_exc):
+    """Return the traceback associated with the exception as a new reference, 
as
+    accessible from Python through __traceback__.  If there is no
+    traceback associated, this returns NULL."""
+    w_tb = space.getattr(w_exc, space.wrap('__traceback__'))
+    if space.is_none(w_tb):
+        return None
+    return w_tb
+
+
+@cpython_api([PyObject, PyObject], rffi.INT_real, error=-1)
+def PyException_SetTraceback(space, w_exc, w_tb):
+    """Set the traceback associated with the exception to tb.  Use Py_None to
+    clear it."""
+    space.setattr(w_exc, space.wrap('__traceback__'), w_tb)
+    return 0
+
+
+@cpython_api([PyObject], PyObject)
+def PyException_GetContext(space, w_exc):
+    """Return the context (another exception instance during whose handling ex 
was
+    raised) associated with the exception as a new reference, as accessible 
from
+    Python through __context__.  If there is no context associated, this
+    returns NULL."""
+    w_ctx = space.getattr(w_exc, space.wrap('__context__'))
+    if space.is_none(w_ctx):
+        return None
+    return w_ctx
+
+
+@cpython_api([PyObject, PyObject], lltype.Void)
+def PyException_SetContext(space, w_exc, ctx):
+    """Set the context associated with the exception to ctx.  Use NULL to clear
+    it.  There is no type check to make sure that ctx is an exception instance.
+    This steals a reference to ctx."""
+    if ctx:
+        w_ctx = from_ref(space, ctx)
+        Py_DecRef(space, ctx)
+    else:
+        w_ctx = space.w_None
+    space.setattr(w_exc, space.wrap('__context__'), w_ctx)
+
+@cpython_api([PyObject], PyObject)
+def PyException_GetCause(space, w_exc):
+    """Return the cause (another exception instance set by raise ... from ...)
+    associated with the exception as a new reference, as accessible from Python
+    through __cause__.  If there is no cause associated, this returns
+    NULL."""
+    w_cause = space.getattr(w_exc, space.wrap('__cause__'))
+    if space.is_none(w_cause):
+        return None
+    return w_cause
+
+
+@cpython_api([PyObject, PyObject], lltype.Void)
+def PyException_SetCause(space, w_exc, cause):
+    """Set the cause associated with the exception to cause.  Use NULL to clear
+    it.  There is no type check to make sure that cause is an exception 
instance.
+    This steals a reference to cause."""
+    if cause:
+        w_cause = from_ref(space, cause)
+        Py_DecRef(space, cause)
+    else:
+        w_cause = space.w_None
+    space.setattr(w_exc, space.wrap('__cause__'), w_cause)
+
diff --git a/pypy/module/cpyext/pyerrors.py b/pypy/module/cpyext/pyerrors.py
--- a/pypy/module/cpyext/pyerrors.py
+++ b/pypy/module/cpyext/pyerrors.py
@@ -40,10 +40,6 @@
     state = space.fromcache(State)
     state.clear_exception()
 
-@cpython_api([PyObject], PyObject)
-def PyExceptionInstance_Class(space, w_obj):
-    return space.type(w_obj)
-
 @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.
diff --git a/pypy/module/cpyext/stubs.py b/pypy/module/cpyext/stubs.py
--- a/pypy/module/cpyext/stubs.py
+++ b/pypy/module/cpyext/stubs.py
@@ -532,55 +532,6 @@
     raise NotImplementedError
     
 
-@cpython_api([PyObject], PyObject)
-def PyException_GetTraceback(space, ex):
-    """Return the traceback associated with the exception as a new reference, 
as
-    accessible from Python through __traceback__.  If there is no
-    traceback associated, this returns NULL."""
-    raise NotImplementedError
-    
-
-@cpython_api([PyObject, PyObject], rffi.INT_real, error=-1)
-def PyException_SetTraceback(space, ex, tb):
-    """Set the traceback associated with the exception to tb.  Use Py_None to
-    clear it."""
-    raise NotImplementedError
-    
-
-@cpython_api([PyObject], PyObject)
-def PyException_GetContext(space, ex):
-    """Return the context (another exception instance during whose handling ex 
was
-    raised) associated with the exception as a new reference, as accessible 
from
-    Python through __context__.  If there is no context associated, this
-    returns NULL."""
-    raise NotImplementedError
-    
-
-@cpython_api([PyObject, PyObject], lltype.Void)
-def PyException_SetContext(space, ex, ctx):
-    """Set the context associated with the exception to ctx.  Use NULL to clear
-    it.  There is no type check to make sure that ctx is an exception instance.
-    This steals a reference to ctx."""
-    raise NotImplementedError
-    
-
-@cpython_api([PyObject], PyObject)
-def PyException_GetCause(space, ex):
-    """Return the cause (another exception instance set by raise ... from ...)
-    associated with the exception as a new reference, as accessible from Python
-    through __cause__.  If there is no cause associated, this returns
-    NULL."""
-    raise NotImplementedError
-    
-
-@cpython_api([PyObject, PyObject], lltype.Void)
-def PyException_SetCause(space, ex, ctx):
-    """Set the cause associated with the exception to ctx.  Use NULL to clear
-    it.  There is no type check to make sure that ctx is an exception instance.
-    This steals a reference to ctx."""
-    raise NotImplementedError
-    
-
 @cpython_api([rffi.CCHARP, rffi.CCHARP, Py_ssize_t, Py_ssize_t, Py_ssize_t, 
rffi.CCHARP], PyObject)
 def PyUnicodeDecodeError_Create(space, encoding, object, length, start, end, 
reason):
     """Create a UnicodeDecodeError object with the attributes encoding,
diff --git a/pypy/module/cpyext/test/test_exception.py 
b/pypy/module/cpyext/test/test_exception.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/test/test_exception.py
@@ -0,0 +1,29 @@
+from pypy.module.cpyext.test.test_api import BaseApiTest
+from pypy.module.cpyext.pyobject import make_ref
+
+class TestExceptions(BaseApiTest):
+
+    def test_ExceptionInstance_Class(self, space, api):
+        w_instance = space.call_function(space.w_ValueError)
+        assert api.PyExceptionInstance_Class(w_instance) is space.w_ValueError
+
+    def test_traceback(self, space, api):
+        w_exc = space.call_function(space.w_ValueError)
+        assert api.PyException_GetTraceback(w_exc) is None
+        assert api.PyException_SetTraceback(w_exc, space.wrap(1)) == -1
+        api.PyErr_Clear()
+
+    def test_context(self, space, api):
+        w_exc = space.call_function(space.w_ValueError)
+        assert api.PyException_GetContext(w_exc) is None
+        w_ctx = space.call_function(space.w_IndexError)
+        api.PyException_SetContext(w_exc, make_ref(space, w_ctx))
+        assert space.is_w(api.PyException_GetContext(w_exc), w_ctx)
+
+    def test_cause(self, space, api):
+        w_exc = space.call_function(space.w_ValueError)
+        assert api.PyException_GetCause(w_exc) is None
+        w_cause = space.call_function(space.w_IndexError)
+        api.PyException_SetCause(w_exc, make_ref(space, w_cause))
+        assert space.is_w(api.PyException_GetCause(w_exc), w_cause)
+
diff --git a/pypy/module/cpyext/test/test_pyerrors.py 
b/pypy/module/cpyext/test/test_pyerrors.py
--- a/pypy/module/cpyext/test/test_pyerrors.py
+++ b/pypy/module/cpyext/test/test_pyerrors.py
@@ -87,10 +87,6 @@
         out, err = capfd.readouterr()
         assert "Exception ValueError: 'message' in 'location' ignored" == 
err.strip()
 
-    def test_ExceptionInstance_Class(self, space, api):
-        instance = space.call_function(space.w_ValueError)
-        assert api.PyExceptionInstance_Class(instance) is space.w_ValueError
-
 class AppTestFetch(AppTestCpythonExtensionBase):
     def setup_class(cls):
         AppTestCpythonExtensionBase.setup_class.im_func(cls)
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to