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