diff options
Diffstat (limited to 'Lib/test/test_raise.py')
-rw-r--r-- | Lib/test/test_raise.py | 383 |
1 files changed, 383 insertions, 0 deletions
diff --git a/Lib/test/test_raise.py b/Lib/test/test_raise.py new file mode 100644 index 00000000000..e02c1af1314 --- /dev/null +++ b/Lib/test/test_raise.py @@ -0,0 +1,383 @@ +# Copyright 2007 Google, Inc. All Rights Reserved. +# Licensed to PSF under a Contributor Agreement. + +"""Tests for the raise statement.""" + +from test import support +import sys +import types +import unittest + + +def get_tb(): + try: + raise OSError() + except: + return sys.exc_info()[2] + + +class Context: + def __enter__(self): + return self + def __exit__(self, exc_type, exc_value, exc_tb): + return True + + +class TestRaise(unittest.TestCase): + def test_invalid_reraise(self): + try: + raise + except RuntimeError as e: + self.assertIn("No active exception", str(e)) + else: + self.fail("No exception raised") + + def test_reraise(self): + try: + try: + raise IndexError() + except IndexError as e: + exc1 = e + raise + except IndexError as exc2: + self.assertTrue(exc1 is exc2) + else: + self.fail("No exception raised") + + def test_except_reraise(self): + def reraise(): + try: + raise TypeError("foo") + except: + try: + raise KeyError("caught") + except KeyError: + pass + raise + self.assertRaises(TypeError, reraise) + + def test_finally_reraise(self): + def reraise(): + try: + raise TypeError("foo") + except: + try: + raise KeyError("caught") + finally: + raise + self.assertRaises(KeyError, reraise) + + def test_nested_reraise(self): + def nested_reraise(): + raise + def reraise(): + try: + raise TypeError("foo") + except: + nested_reraise() + self.assertRaises(TypeError, reraise) + + def test_with_reraise1(self): + def reraise(): + try: + raise TypeError("foo") + except: + with Context(): + pass + raise + self.assertRaises(TypeError, reraise) + + def test_with_reraise2(self): + def reraise(): + try: + raise TypeError("foo") + except: + with Context(): + raise KeyError("caught") + raise + self.assertRaises(TypeError, reraise) + + def test_yield_reraise(self): + def reraise(): + try: + raise TypeError("foo") + except: + yield 1 + raise + g = reraise() + next(g) + self.assertRaises(TypeError, lambda: next(g)) + self.assertRaises(StopIteration, lambda: next(g)) + + def test_erroneous_exception(self): + class MyException(Exception): + def __init__(self): + raise RuntimeError() + + try: + raise MyException + except RuntimeError: + pass + else: + self.fail("No exception raised") + + def test_new_returns_invalid_instance(self): + # See issue #11627. + class MyException(Exception): + def __new__(cls, *args): + return object() + + with self.assertRaises(TypeError): + raise MyException + + +class TestCause(unittest.TestCase): + def test_invalid_cause(self): + try: + raise IndexError from 5 + except TypeError as e: + self.assertIn("exception cause", str(e)) + else: + self.fail("No exception raised") + + def test_class_cause(self): + try: + raise IndexError from KeyError + except IndexError as e: + self.assertIsInstance(e.__cause__, KeyError) + else: + self.fail("No exception raised") + + def test_instance_cause(self): + cause = KeyError() + try: + raise IndexError from cause + except IndexError as e: + self.assertTrue(e.__cause__ is cause) + else: + self.fail("No exception raised") + + def test_erroneous_cause(self): + class MyException(Exception): + def __init__(self): + raise RuntimeError() + + try: + raise IndexError from MyException + except RuntimeError: + pass + else: + self.fail("No exception raised") + + +class TestTraceback(unittest.TestCase): + def test_sets_traceback(self): + try: + raise IndexError() + except IndexError as e: + self.assertIsInstance(e.__traceback__, types.TracebackType) + else: + self.fail("No exception raised") + + def test_accepts_traceback(self): + tb = get_tb() + try: + raise IndexError().with_traceback(tb) + except IndexError as e: + self.assertNotEqual(e.__traceback__, tb) + self.assertEqual(e.__traceback__.tb_next, tb) + else: + self.fail("No exception raised") + + +class TestContext(unittest.TestCase): + def test_instance_context_instance_raise(self): + context = IndexError() + try: + try: + raise context + except: + raise OSError() + except OSError as e: + self.assertEqual(e.__context__, context) + else: + self.fail("No exception raised") + + def test_class_context_instance_raise(self): + context = IndexError + try: + try: + raise context + except: + raise OSError() + except OSError as e: + self.assertNotEqual(e.__context__, context) + self.assertIsInstance(e.__context__, context) + else: + self.fail("No exception raised") + + def test_class_context_class_raise(self): + context = IndexError + try: + try: + raise context + except: + raise OSError + except OSError as e: + self.assertNotEqual(e.__context__, context) + self.assertIsInstance(e.__context__, context) + else: + self.fail("No exception raised") + + def test_c_exception_context(self): + try: + try: + 1/0 + except: + raise OSError + except OSError as e: + self.assertIsInstance(e.__context__, ZeroDivisionError) + else: + self.fail("No exception raised") + + def test_c_exception_raise(self): + try: + try: + 1/0 + except: + xyzzy + except NameError as e: + self.assertIsInstance(e.__context__, ZeroDivisionError) + else: + self.fail("No exception raised") + + def test_noraise_finally(self): + try: + try: + pass + finally: + raise OSError + except OSError as e: + self.assertTrue(e.__context__ is None) + else: + self.fail("No exception raised") + + def test_raise_finally(self): + try: + try: + 1/0 + finally: + raise OSError + except OSError as e: + self.assertIsInstance(e.__context__, ZeroDivisionError) + else: + self.fail("No exception raised") + + def test_context_manager(self): + class ContextManager: + def __enter__(self): + pass + def __exit__(self, t, v, tb): + xyzzy + try: + with ContextManager(): + 1/0 + except NameError as e: + self.assertIsInstance(e.__context__, ZeroDivisionError) + else: + self.fail("No exception raised") + + def test_cycle_broken(self): + # Self-cycles (when re-raising a caught exception) are broken + try: + try: + 1/0 + except ZeroDivisionError as e: + raise e + except ZeroDivisionError as e: + self.assertTrue(e.__context__ is None, e.__context__) + + def test_reraise_cycle_broken(self): + # Non-trivial context cycles (through re-raising a previous exception) + # are broken too. + try: + try: + xyzzy + except NameError as a: + try: + 1/0 + except ZeroDivisionError: + raise a + except NameError as e: + self.assertTrue(e.__context__.__context__ is None) + + def test_3118(self): + # deleting the generator caused the __context__ to be cleared + def gen(): + try: + yield 1 + finally: + pass + + def f(): + g = gen() + next(g) + try: + try: + raise ValueError + except: + del g + raise KeyError + except Exception as e: + self.assertIsInstance(e.__context__, ValueError) + + f() + + def test_3611(self): + # A re-raised exception in a __del__ caused the __context__ + # to be cleared + class C: + def __del__(self): + try: + 1/0 + except: + raise + + def f(): + x = C() + try: + try: + x.x + except AttributeError: + del x + raise TypeError + except Exception as e: + self.assertNotEqual(e.__context__, None) + self.assertIsInstance(e.__context__, AttributeError) + + with support.captured_output("stderr"): + f() + +class TestRemovedFunctionality(unittest.TestCase): + def test_tuples(self): + try: + raise (IndexError, KeyError) # This should be a tuple! + except TypeError: + pass + else: + self.fail("No exception raised") + + def test_strings(self): + try: + raise "foo" + except TypeError: + pass + else: + self.fail("No exception raised") + + +def test_main(): + support.run_unittest(__name__) + +if __name__ == "__main__": + unittest.main() |