mirror of
				https://github.com/python/cpython.git
				synced 2025-11-04 03:44:55 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			383 lines
		
	
	
	
		
			10 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			383 lines
		
	
	
	
		
			10 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
# 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()
 |