[pypy-commit] pypy py3k: Add traceback to exception objects.

amauryfa noreply at buildbot.pypy.org
Wed Oct 19 23:11:10 CEST 2011


Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: py3k
Changeset: r48237:e279f4abab78
Date: 2011-10-19 22:31 +0200
http://bitbucket.org/pypy/pypy/changeset/e279f4abab78/

Log:	Add traceback to exception objects. Not filled by the interpreter
	yet, at least with_traceback() won't fail.

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
@@ -78,6 +78,7 @@
     descr_set_dict, descr_del_dict)
 from pypy.interpreter.gateway import interp2app
 from pypy.interpreter.error import OperationError
+from pypy.interpreter.pytraceback import PyTraceback
 from pypy.rlib import rwin32
 
 def readwrite_attrproperty_w(name, cls):
@@ -97,6 +98,7 @@
     args_w = []
     w_cause = None
     w_context = None
+    w_traceback = None
 
     def __init__(self, space):
         self.w_message = space.w_None
@@ -169,6 +171,14 @@
                     "derive from BaseException"))
         self.w_context = w_newcontext
 
+    def descr_gettraceback(self, space):
+        return self.w_traceback
+
+    def descr_settraceback(self, space, w_newtraceback):
+        # Check argument
+        space.interp_w(PyTraceback, w_newtraceback, can_be_None=True)
+        self.w_traceback = w_newtraceback
+
     def descr_getitem(self, space, w_index):
         return space.getitem(space.newtuple(self.args_w), w_index)
 
@@ -192,6 +202,10 @@
         w_olddict = self.getdict(space)
         space.call_method(w_olddict, 'update', w_dict)
 
+    def descr_with_traceback(self, space, w_traceback):
+        self.descr_settraceback(space, w_traceback)
+        return space.wrap(self)
+
     def descr_message_get(self, space):
         w_dict = self.w_dict
         if w_dict is not None:
@@ -242,6 +256,7 @@
     __getitem__ = interp2app(W_BaseException.descr_getitem),
     __reduce__ = interp2app(W_BaseException.descr_reduce),
     __setstate__ = interp2app(W_BaseException.descr_setstate),
+    with_traceback = interp2app(W_BaseException.descr_with_traceback),
     message = GetSetProperty(W_BaseException.descr_message_get,
                             W_BaseException.descr_message_set,
                             W_BaseException.descr_message_del),
@@ -251,6 +266,8 @@
                                W_BaseException.descr_setcause),
     __context__ = GetSetProperty(W_BaseException.descr_getcontext,
                                  W_BaseException.descr_setcontext),
+    __traceback__ = GetSetProperty(W_BaseException.descr_gettraceback,
+                                   W_BaseException.descr_settraceback),
 )
 
 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
@@ -261,3 +261,13 @@
         raises(TypeError, setattr, e1, '__context__', 1)
         raises(AttributeError, delattr, e1, '__context__')
 
+    def test_traceback(self):
+        assert ValueError().with_traceback(None).__traceback__ is None
+        raises(TypeError, ValueError().with_traceback, 3)
+        try:
+            XXX
+        except NameError as e:
+            import sys
+            tb = sys.exc_info()[2]
+            assert e.with_traceback(tb) is e
+            assert e.__traceback__ is tb


More information about the pypy-commit mailing list