Commits

Amaury Forgeot d'Arc committed 92a51ef

cpyext: Implement PyException_* functions.

Comments (0)

Files changed (6)

pypy/module/cpyext/__init__.py

 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

pypy/module/cpyext/exception.py

+# 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)
+

pypy/module/cpyext/pyerrors.py

     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.

pypy/module/cpyext/stubs.py

     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,

pypy/module/cpyext/test/test_exception.py

+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)
+

pypy/module/cpyext/test/test_pyerrors.py

         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)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.