1# Copyright 2007 Google, Inc. All Rights Reserved. 2# Licensed to PSF under a Contributor Agreement. 3 4"""Tests for the raise statement.""" 5 6from test import support 7import sys 8import types 9import unittest 10 11 12def get_tb(): 13 try: 14 raise OSError() 15 except: 16 return sys.exc_info()[2] 17 18 19class Context: 20 def __enter__(self): 21 return self 22 def __exit__(self, exc_type, exc_value, exc_tb): 23 return True 24 25 26class TestRaise(unittest.TestCase): 27 def test_invalid_reraise(self): 28 try: 29 raise 30 except RuntimeError as e: 31 self.assertIn("No active exception", str(e)) 32 else: 33 self.fail("No exception raised") 34 35 def test_reraise(self): 36 try: 37 try: 38 raise IndexError() 39 except IndexError as e: 40 exc1 = e 41 raise 42 except IndexError as exc2: 43 self.assertIs(exc1, exc2) 44 else: 45 self.fail("No exception raised") 46 47 def test_except_reraise(self): 48 def reraise(): 49 try: 50 raise TypeError("foo") 51 except: 52 try: 53 raise KeyError("caught") 54 except KeyError: 55 pass 56 raise 57 self.assertRaises(TypeError, reraise) 58 59 def test_finally_reraise(self): 60 def reraise(): 61 try: 62 raise TypeError("foo") 63 except: 64 try: 65 raise KeyError("caught") 66 finally: 67 raise 68 self.assertRaises(KeyError, reraise) 69 70 def test_nested_reraise(self): 71 def nested_reraise(): 72 raise 73 def reraise(): 74 try: 75 raise TypeError("foo") 76 except: 77 nested_reraise() 78 self.assertRaises(TypeError, reraise) 79 80 def test_raise_from_None(self): 81 try: 82 try: 83 raise TypeError("foo") 84 except: 85 raise ValueError() from None 86 except ValueError as e: 87 self.assertIsInstance(e.__context__, TypeError) 88 self.assertIsNone(e.__cause__) 89 90 def test_with_reraise1(self): 91 def reraise(): 92 try: 93 raise TypeError("foo") 94 except: 95 with Context(): 96 pass 97 raise 98 self.assertRaises(TypeError, reraise) 99 100 def test_with_reraise2(self): 101 def reraise(): 102 try: 103 raise TypeError("foo") 104 except: 105 with Context(): 106 raise KeyError("caught") 107 raise 108 self.assertRaises(TypeError, reraise) 109 110 def test_yield_reraise(self): 111 def reraise(): 112 try: 113 raise TypeError("foo") 114 except: 115 yield 1 116 raise 117 g = reraise() 118 next(g) 119 self.assertRaises(TypeError, lambda: next(g)) 120 self.assertRaises(StopIteration, lambda: next(g)) 121 122 def test_erroneous_exception(self): 123 class MyException(Exception): 124 def __init__(self): 125 raise RuntimeError() 126 127 try: 128 raise MyException 129 except RuntimeError: 130 pass 131 else: 132 self.fail("No exception raised") 133 134 def test_new_returns_invalid_instance(self): 135 # See issue #11627. 136 class MyException(Exception): 137 def __new__(cls, *args): 138 return object() 139 140 with self.assertRaises(TypeError): 141 raise MyException 142 143 def test_assert_with_tuple_arg(self): 144 try: 145 assert False, (3,) 146 except AssertionError as e: 147 self.assertEqual(str(e), "(3,)") 148 149 150 151class TestCause(unittest.TestCase): 152 153 def testCauseSyntax(self): 154 try: 155 try: 156 try: 157 raise TypeError 158 except Exception: 159 raise ValueError from None 160 except ValueError as exc: 161 self.assertIsNone(exc.__cause__) 162 self.assertTrue(exc.__suppress_context__) 163 exc.__suppress_context__ = False 164 raise exc 165 except ValueError as exc: 166 e = exc 167 168 self.assertIsNone(e.__cause__) 169 self.assertFalse(e.__suppress_context__) 170 self.assertIsInstance(e.__context__, TypeError) 171 172 def test_invalid_cause(self): 173 try: 174 raise IndexError from 5 175 except TypeError as e: 176 self.assertIn("exception cause", str(e)) 177 else: 178 self.fail("No exception raised") 179 180 def test_class_cause(self): 181 try: 182 raise IndexError from KeyError 183 except IndexError as e: 184 self.assertIsInstance(e.__cause__, KeyError) 185 else: 186 self.fail("No exception raised") 187 188 def test_instance_cause(self): 189 cause = KeyError() 190 try: 191 raise IndexError from cause 192 except IndexError as e: 193 self.assertIs(e.__cause__, cause) 194 else: 195 self.fail("No exception raised") 196 197 def test_erroneous_cause(self): 198 class MyException(Exception): 199 def __init__(self): 200 raise RuntimeError() 201 202 try: 203 raise IndexError from MyException 204 except RuntimeError: 205 pass 206 else: 207 self.fail("No exception raised") 208 209 210class TestTraceback(unittest.TestCase): 211 212 def test_sets_traceback(self): 213 try: 214 raise IndexError() 215 except IndexError as e: 216 self.assertIsInstance(e.__traceback__, types.TracebackType) 217 else: 218 self.fail("No exception raised") 219 220 def test_accepts_traceback(self): 221 tb = get_tb() 222 try: 223 raise IndexError().with_traceback(tb) 224 except IndexError as e: 225 self.assertNotEqual(e.__traceback__, tb) 226 self.assertEqual(e.__traceback__.tb_next, tb) 227 else: 228 self.fail("No exception raised") 229 230 231class TestTracebackType(unittest.TestCase): 232 233 def raiser(self): 234 raise ValueError 235 236 def test_attrs(self): 237 try: 238 self.raiser() 239 except Exception as exc: 240 tb = exc.__traceback__ 241 242 self.assertIsInstance(tb.tb_next, types.TracebackType) 243 self.assertIs(tb.tb_frame, sys._getframe()) 244 self.assertIsInstance(tb.tb_lasti, int) 245 self.assertIsInstance(tb.tb_lineno, int) 246 247 self.assertIs(tb.tb_next.tb_next, None) 248 249 # Invalid assignments 250 with self.assertRaises(TypeError): 251 del tb.tb_next 252 253 with self.assertRaises(TypeError): 254 tb.tb_next = "asdf" 255 256 # Loops 257 with self.assertRaises(ValueError): 258 tb.tb_next = tb 259 260 with self.assertRaises(ValueError): 261 tb.tb_next.tb_next = tb 262 263 # Valid assignments 264 tb.tb_next = None 265 self.assertIs(tb.tb_next, None) 266 267 new_tb = get_tb() 268 tb.tb_next = new_tb 269 self.assertIs(tb.tb_next, new_tb) 270 271 def test_constructor(self): 272 other_tb = get_tb() 273 frame = sys._getframe() 274 275 tb = types.TracebackType(other_tb, frame, 1, 2) 276 self.assertEqual(tb.tb_next, other_tb) 277 self.assertEqual(tb.tb_frame, frame) 278 self.assertEqual(tb.tb_lasti, 1) 279 self.assertEqual(tb.tb_lineno, 2) 280 281 tb = types.TracebackType(None, frame, 1, 2) 282 self.assertEqual(tb.tb_next, None) 283 284 with self.assertRaises(TypeError): 285 types.TracebackType("no", frame, 1, 2) 286 287 with self.assertRaises(TypeError): 288 types.TracebackType(other_tb, "no", 1, 2) 289 290 with self.assertRaises(TypeError): 291 types.TracebackType(other_tb, frame, "no", 2) 292 293 with self.assertRaises(TypeError): 294 types.TracebackType(other_tb, frame, 1, "nuh-uh") 295 296 297class TestContext(unittest.TestCase): 298 def test_instance_context_instance_raise(self): 299 context = IndexError() 300 try: 301 try: 302 raise context 303 except: 304 raise OSError() 305 except OSError as e: 306 self.assertEqual(e.__context__, context) 307 else: 308 self.fail("No exception raised") 309 310 def test_class_context_instance_raise(self): 311 context = IndexError 312 try: 313 try: 314 raise context 315 except: 316 raise OSError() 317 except OSError as e: 318 self.assertNotEqual(e.__context__, context) 319 self.assertIsInstance(e.__context__, context) 320 else: 321 self.fail("No exception raised") 322 323 def test_class_context_class_raise(self): 324 context = IndexError 325 try: 326 try: 327 raise context 328 except: 329 raise OSError 330 except OSError as e: 331 self.assertNotEqual(e.__context__, context) 332 self.assertIsInstance(e.__context__, context) 333 else: 334 self.fail("No exception raised") 335 336 def test_c_exception_context(self): 337 try: 338 try: 339 1/0 340 except: 341 raise OSError 342 except OSError as e: 343 self.assertIsInstance(e.__context__, ZeroDivisionError) 344 else: 345 self.fail("No exception raised") 346 347 def test_c_exception_raise(self): 348 try: 349 try: 350 1/0 351 except: 352 xyzzy 353 except NameError as e: 354 self.assertIsInstance(e.__context__, ZeroDivisionError) 355 else: 356 self.fail("No exception raised") 357 358 def test_noraise_finally(self): 359 try: 360 try: 361 pass 362 finally: 363 raise OSError 364 except OSError as e: 365 self.assertIsNone(e.__context__) 366 else: 367 self.fail("No exception raised") 368 369 def test_raise_finally(self): 370 try: 371 try: 372 1/0 373 finally: 374 raise OSError 375 except OSError as e: 376 self.assertIsInstance(e.__context__, ZeroDivisionError) 377 else: 378 self.fail("No exception raised") 379 380 def test_context_manager(self): 381 class ContextManager: 382 def __enter__(self): 383 pass 384 def __exit__(self, t, v, tb): 385 xyzzy 386 try: 387 with ContextManager(): 388 1/0 389 except NameError as e: 390 self.assertIsInstance(e.__context__, ZeroDivisionError) 391 else: 392 self.fail("No exception raised") 393 394 def test_cycle_broken(self): 395 # Self-cycles (when re-raising a caught exception) are broken 396 try: 397 try: 398 1/0 399 except ZeroDivisionError as e: 400 raise e 401 except ZeroDivisionError as e: 402 self.assertIsNone(e.__context__) 403 404 def test_reraise_cycle_broken(self): 405 # Non-trivial context cycles (through re-raising a previous exception) 406 # are broken too. 407 try: 408 try: 409 xyzzy 410 except NameError as a: 411 try: 412 1/0 413 except ZeroDivisionError: 414 raise a 415 except NameError as e: 416 self.assertIsNone(e.__context__.__context__) 417 418 def test_3118(self): 419 # deleting the generator caused the __context__ to be cleared 420 def gen(): 421 try: 422 yield 1 423 finally: 424 pass 425 426 def f(): 427 g = gen() 428 next(g) 429 try: 430 try: 431 raise ValueError 432 except: 433 del g 434 raise KeyError 435 except Exception as e: 436 self.assertIsInstance(e.__context__, ValueError) 437 438 f() 439 440 def test_3611(self): 441 import gc 442 # A re-raised exception in a __del__ caused the __context__ 443 # to be cleared 444 class C: 445 def __del__(self): 446 try: 447 1/0 448 except: 449 raise 450 451 def f(): 452 x = C() 453 try: 454 try: 455 f.x 456 except AttributeError: 457 # make x.__del__ trigger 458 del x 459 gc.collect() # For PyPy or other GCs. 460 raise TypeError 461 except Exception as e: 462 self.assertNotEqual(e.__context__, None) 463 self.assertIsInstance(e.__context__, AttributeError) 464 465 with support.catch_unraisable_exception() as cm: 466 f() 467 468 self.assertEqual(ZeroDivisionError, cm.unraisable.exc_type) 469 470 471class TestRemovedFunctionality(unittest.TestCase): 472 def test_tuples(self): 473 try: 474 raise (IndexError, KeyError) # This should be a tuple! 475 except TypeError: 476 pass 477 else: 478 self.fail("No exception raised") 479 480 def test_strings(self): 481 try: 482 raise "foo" 483 except TypeError: 484 pass 485 else: 486 self.fail("No exception raised") 487 488 489if __name__ == "__main__": 490 unittest.main() 491