|
8 | 8 | from future.builtins import * |
9 | 9 | from future.utils import (old_div, istext, isbytes, native, PY2, PY3, |
10 | 10 | native_str, raise_, as_native_str, ensure_new_type, |
11 | | - bytes_to_native_str) |
| 11 | + bytes_to_native_str, raise_from) |
12 | 12 |
|
13 | 13 | from numbers import Integral |
14 | 14 | from future.tests.base import unittest, skip26 |
@@ -141,7 +141,16 @@ def with_traceback(): |
141 | 141 | except IOError as e: |
142 | 142 | self.assertEqual(str(e), "An error") |
143 | 143 |
|
144 | | - |
| 144 | + def test_raise_from_None(self): |
| 145 | + try: |
| 146 | + try: |
| 147 | + raise TypeError("foo") |
| 148 | + except: |
| 149 | + raise_from(ValueError(), None) |
| 150 | + except ValueError as e: |
| 151 | + self.assertTrue(isinstance(e.__context__, TypeError)) |
| 152 | + self.assertIsNone(e.__cause__) |
| 153 | + |
145 | 154 | @skip26 |
146 | 155 | def test_as_native_str(self): |
147 | 156 | """ |
@@ -190,5 +199,97 @@ def test_bytes_to_native_str(self): |
190 | 199 | self.assertEqual(type(s), native_str) |
191 | 200 |
|
192 | 201 |
|
| 202 | +class TestCause(unittest.TestCase): |
| 203 | + """ |
| 204 | + Except for the first method, these were adapted from Py3.3's |
| 205 | + Lib/test/test_raise.py. |
| 206 | + """ |
| 207 | + def test_normal_use(self): |
| 208 | + """ |
| 209 | + Adapted from PEP 3134 docs |
| 210 | + """ |
| 211 | + # Setup: |
| 212 | + class DatabaseError(Exception): |
| 213 | + pass |
| 214 | + |
| 215 | + # Python 2 and 3: |
| 216 | + from future.utils import raise_from |
| 217 | + |
| 218 | + class FileDatabase: |
| 219 | + def __init__(self, filename): |
| 220 | + try: |
| 221 | + self.file = open(filename) |
| 222 | + except IOError as exc: |
| 223 | + raise_from(DatabaseError('failed to open'), exc) |
| 224 | + |
| 225 | + # Testing the above: |
| 226 | + try: |
| 227 | + fd = FileDatabase('non_existent_file.txt') |
| 228 | + except Exception as e: |
| 229 | + assert isinstance(e.__cause__, IOError) # FileNotFoundError on |
| 230 | + # Py3.3+ inherits from IOError |
| 231 | + |
| 232 | + def testCauseSyntax(self): |
| 233 | + try: |
| 234 | + try: |
| 235 | + try: |
| 236 | + raise TypeError |
| 237 | + except Exception: |
| 238 | + raise_from(ValueError, None) |
| 239 | + except ValueError as exc: |
| 240 | + self.assertIsNone(exc.__cause__) |
| 241 | + self.assertTrue(exc.__suppress_context__) |
| 242 | + exc.__suppress_context__ = False |
| 243 | + raise exc |
| 244 | + except ValueError as exc: |
| 245 | + e = exc |
| 246 | + |
| 247 | + self.assertIsNone(e.__cause__) |
| 248 | + self.assertFalse(e.__suppress_context__) |
| 249 | + self.assertIsInstance(e.__context__, TypeError) |
| 250 | + |
| 251 | + def test_invalid_cause(self): |
| 252 | + try: |
| 253 | + raise_from(IndexError, 5) |
| 254 | + except TypeError as e: |
| 255 | + self.assertIn("exception cause", str(e)) |
| 256 | + else: |
| 257 | + self.fail("No exception raised") |
| 258 | + |
| 259 | + def test_class_cause(self): |
| 260 | + try: |
| 261 | + raise_from(IndexError, KeyError) |
| 262 | + except IndexError as e: |
| 263 | + self.assertIsInstance(e.__cause__, KeyError) |
| 264 | + else: |
| 265 | + self.fail("No exception raised") |
| 266 | + |
| 267 | + @unittest.expectedFailure |
| 268 | + def test_instance_cause(self): |
| 269 | + cause = KeyError('blah') |
| 270 | + try: |
| 271 | + raise_from(IndexError, cause) |
| 272 | + except IndexError as e: |
| 273 | + # FAILS: |
| 274 | + self.assertTrue(e.__cause__ is cause) |
| 275 | + # Even this weaker version seems to fail, although repr(cause) looks correct. |
| 276 | + # Is there something strange about testing exceptions for equality? |
| 277 | + self.assertEqual(e.__cause__, cause) |
| 278 | + else: |
| 279 | + self.fail("No exception raised") |
| 280 | + |
| 281 | + def test_erroneous_cause(self): |
| 282 | + class MyException(Exception): |
| 283 | + def __init__(self): |
| 284 | + raise RuntimeError() |
| 285 | + |
| 286 | + try: |
| 287 | + raise_from(IndexError, MyException) |
| 288 | + except RuntimeError: |
| 289 | + pass |
| 290 | + else: |
| 291 | + self.fail("No exception raised") |
| 292 | + |
| 293 | + |
193 | 294 | if __name__ == '__main__': |
194 | 295 | unittest.main() |
0 commit comments