[pypy-commit] pypy py3k: Add Exception.__cause__ and __context__

amauryfa noreply at buildbot.pypy.org
Thu Oct 13 22:40:27 CEST 2011


Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: py3k
Changeset: r48032:47a171031fd3
Date: 2011-10-13 22:38 +0200
http://bitbucket.org/pypy/pypy/changeset/47a171031fd3/

Log:	Add Exception.__cause__ and __context__

diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py
--- a/pypy/interpreter/pyopcode.py
+++ b/pypy/interpreter/pyopcode.py
@@ -491,7 +491,7 @@
 
         w_value = w_cause = space.w_None
         if nbargs >= 2:
-            w_cause = self.popvalue() # XXX cause?
+            w_cause = self.popvalue()
         if 1:
             w_value = self.popvalue()
         if space.exception_is_valid_obj_as_class_w(w_value):
@@ -499,6 +499,7 @@
             w_value = space.call_function(w_type)
         else:
             w_type = space.type(w_value)
+        w_value.w_cause = w_cause
         operror = OperationError(w_type, w_value)
         operror.normalize_exception(space)
         w_traceback = space.w_None # XXX with_traceback?
diff --git a/pypy/module/exceptions/interp_exceptions.py b/pypy/module/exceptions/interp_exceptions.py
--- a/pypy/module/exceptions/interp_exceptions.py
+++ b/pypy/module/exceptions/interp_exceptions.py
@@ -95,6 +95,8 @@
     """
     w_dict = None
     args_w = []
+    w_cause = None
+    w_context = None
 
     def __init__(self, space):
         self.w_message = space.w_None
@@ -145,6 +147,28 @@
     def descr_setargs(self, space, w_newargs):
         self.args_w = space.fixedview(w_newargs)
 
+    def descr_getcause(self, space):
+        return self.w_cause
+
+    def descr_setcause(self, space, w_newcause):
+        if not (space.is_w(w_newcause, space.w_None) or
+                space.exception_is_valid_class_w(space.type(w_newcause))):
+            raise OperationError(space.w_TypeError, space.wrap(
+                    "exception cause must be None or "
+                    "derive from BaseException"))
+        self.w_cause = w_newcause
+
+    def descr_getcontext(self, space):
+        return self.w_context
+
+    def descr_setcontext(self, space, w_newcontext):
+        if not (space.is_w(w_newcontext, space.w_None) or
+                space.exception_is_valid_class_w(space.type(w_newcontext))):
+            raise OperationError(space.w_TypeError, space.wrap(
+                    "exception context must be None or "
+                    "derive from BaseException"))
+        self.w_context = w_newcontext
+
     def descr_getitem(self, space, w_index):
         return space.getitem(space.newtuple(self.args_w), w_index)
 
@@ -223,6 +247,10 @@
                             W_BaseException.descr_message_del),
     args = GetSetProperty(W_BaseException.descr_getargs,
                           W_BaseException.descr_setargs),
+    __cause__ = GetSetProperty(W_BaseException.descr_getcause,
+                               W_BaseException.descr_setcause),
+    __context__ = GetSetProperty(W_BaseException.descr_getcontext,
+                                 W_BaseException.descr_setcontext),
 )
 
 def _new_exception(name, base, docstring, **kwargs):
diff --git a/pypy/module/exceptions/test/test_exc.py b/pypy/module/exceptions/test/test_exc.py
--- a/pypy/module/exceptions/test/test_exc.py
+++ b/pypy/module/exceptions/test/test_exc.py
@@ -241,3 +241,23 @@
         assert fw.z == 1
         assert fw.xyz == (1, 2)
 
+    def test_cause(self):
+        e1 = TypeError()
+        e2 = ValueError()
+        assert e1.__cause__ is None
+        e1.__cause__ = e2
+        assert e1.__cause__ is e2
+        e1.__cause__ = None
+        raises(TypeError, setattr, e1, '__cause__', 1)
+        raises(AttributeError, delattr, e1, '__cause__')
+
+    def test_context(self):
+        e1 = TypeError()
+        e2 = ValueError()
+        assert e1.__context__ is None
+        e1.__context__ = e2
+        assert e1.__context__ is e2
+        e1.__context__ = None
+        raises(TypeError, setattr, e1, '__context__', 1)
+        raises(AttributeError, delattr, e1, '__context__')
+


More information about the pypy-commit mailing list