← Back to team overview

testtools-dev team mailing list archive

[Merge] lp:~gz/testtools/py3k_reraise into lp:testtools

 

Martin Packman has proposed merging lp:~gz/testtools/py3k_reraise into lp:testtools.

Requested reviews:
  testtools committers (testtools-committers)

For more details, see:
https://code.launchpad.net/~gz/testtools/py3k_reraise/+merge/116835

Correct the version of reraise used on py3k to not rely on how exception classes are constructed.

Not setting args to allow exception reconstruction is pretty common (bzrlib, and various places in the standard library such as xmlrpc(?:lib|\.client).ProtocolError), and there's no need to construct a new exception instance.

See also more reasoning at:
<https://code.launchpad.net/~gz/apport/py3k_exc_reraise_1024836/+merge/116827>
-- 
https://code.launchpad.net/~gz/testtools/py3k_reraise/+merge/116835
Your team testtools developers is subscribed to branch lp:testtools.
=== modified file 'testtools/_compat3x.py'
--- testtools/_compat3x.py	2011-07-26 23:08:51 +0000
+++ testtools/_compat3x.py	2012-07-26 11:30:52 +0000
@@ -13,5 +13,5 @@
 
 def reraise(exc_class, exc_obj, exc_tb, _marker=object()):
     """Re-raise an exception received from sys.exc_info() or similar."""
-    raise exc_class(*exc_obj.args).with_traceback(exc_tb)
+    raise exc_obj.with_traceback(exc_tb)
 

=== modified file 'testtools/tests/test_compat.py'
--- testtools/tests/test_compat.py	2011-12-21 01:23:49 +0000
+++ testtools/tests/test_compat.py	2012-07-26 11:30:52 +0000
@@ -15,6 +15,7 @@
     _detect_encoding,
     _get_source_encoding,
     _u,
+    reraise,
     str_is_unicode,
     text_repr,
     unicode_output_stream,
@@ -389,6 +390,43 @@
             self.assertEqual(eval(actual), u)
 
 
+
+class TestReraise(testtools.TestCase):
+    """Tests for trivial reraise wrapper needed for Python 2/3 changes"""
+
+    def test_exc_info(self):
+        """After reraise exc_info matches plus some extra traceback"""
+        try:
+            raise ValueError("Bad value")
+        except ValueError:
+            _exc_info = sys.exc_info()
+        try:
+            reraise(*_exc_info)
+        except ValueError:
+            _new_exc_info = sys.exc_info()
+        self.assertIs(_exc_info[0], _new_exc_info[0])
+        self.assertIs(_exc_info[1], _new_exc_info[1])
+        expected_tb = traceback.extract_tb(_exc_info[2])
+        self.assertEqual(expected_tb,
+            traceback.extract_tb(_new_exc_info[2])[-len(expected_tb):])
+
+    def test_custom_exception_no_args(self):
+        """Reraising does not require args attribute to contain params"""
+
+        class CustomException(Exception):
+            """Exception that expects and sets attrs but not args"""
+
+            def __init__(self, value):
+                Exception.__init__(self)
+                self.value = value
+
+        try:
+            raise CustomException("Some value")
+        except CustomException:
+            _exc_info = sys.exc_info()
+        self.assertRaises(CustomException, reraise, *_exc_info)
+
+
 def test_suite():
     from unittest import TestLoader
     return TestLoader().loadTestsFromName(__name__)


Follow ups