| 
									
										
										
										
											2006-02-28 18:44:41 +00:00
										 |  |  | #!/usr/bin/env python | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | """Unit tests for the with statement specified in PEP 343.""" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-28 19:02:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-28 18:44:41 +00:00
										 |  |  | __author__ = "Mike Bland" | 
					
						
							|  |  |  | __email__ = "mbland at acm dot org" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-28 21:57:43 +00:00
										 |  |  | import sys | 
					
						
							| 
									
										
										
										
											2006-02-28 18:44:41 +00:00
										 |  |  | import unittest | 
					
						
							| 
									
										
										
										
											2006-02-28 21:57:43 +00:00
										 |  |  | from collections import deque | 
					
						
							| 
									
										
										
										
											2006-05-03 13:02:47 +00:00
										 |  |  | from contextlib import GeneratorContextManager, contextmanager | 
					
						
							| 
									
										
										
										
											2006-02-28 18:44:41 +00:00
										 |  |  | from test.test_support import run_unittest | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-03 13:02:47 +00:00
										 |  |  | class MockContextManager(GeneratorContextManager): | 
					
						
							| 
									
										
										
										
											2006-02-28 18:44:41 +00:00
										 |  |  |     def __init__(self, gen): | 
					
						
							| 
									
										
										
										
											2006-05-03 13:02:47 +00:00
										 |  |  |         GeneratorContextManager.__init__(self, gen) | 
					
						
							| 
									
										
										
										
											2006-02-28 18:44:41 +00:00
										 |  |  |         self.enter_called = False | 
					
						
							|  |  |  |         self.exit_called = False | 
					
						
							|  |  |  |         self.exit_args = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __enter__(self): | 
					
						
							|  |  |  |         self.enter_called = True | 
					
						
							| 
									
										
										
										
											2006-05-03 13:02:47 +00:00
										 |  |  |         return GeneratorContextManager.__enter__(self) | 
					
						
							| 
									
										
										
										
											2006-02-28 18:44:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def __exit__(self, type, value, traceback): | 
					
						
							|  |  |  |         self.exit_called = True | 
					
						
							|  |  |  |         self.exit_args = (type, value, traceback) | 
					
						
							| 
									
										
										
										
											2006-05-03 13:02:47 +00:00
										 |  |  |         return GeneratorContextManager.__exit__(self, type, | 
					
						
							|  |  |  |                                                 value, traceback) | 
					
						
							| 
									
										
										
										
											2006-02-28 18:44:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def mock_contextmanager(func): | 
					
						
							|  |  |  |     def helper(*args, **kwds): | 
					
						
							|  |  |  |         return MockContextManager(func(*args, **kwds)) | 
					
						
							|  |  |  |     return helper | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class MockResource(object): | 
					
						
							|  |  |  |     def __init__(self): | 
					
						
							|  |  |  |         self.yielded = False | 
					
						
							|  |  |  |         self.stopped = False | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_contextmanager | 
					
						
							|  |  |  | def mock_contextmanager_generator(): | 
					
						
							|  |  |  |     mock = MockResource() | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         mock.yielded = True | 
					
						
							|  |  |  |         yield mock | 
					
						
							|  |  |  |     finally: | 
					
						
							|  |  |  |         mock.stopped = True | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-28 21:57:43 +00:00
										 |  |  | class Nested(object): | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-02 19:47:52 +00:00
										 |  |  |     def __init__(self, *managers): | 
					
						
							|  |  |  |         self.managers = managers | 
					
						
							| 
									
										
										
										
											2006-02-28 21:57:43 +00:00
										 |  |  |         self.entered = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __enter__(self): | 
					
						
							|  |  |  |         if self.entered is not None: | 
					
						
							|  |  |  |             raise RuntimeError("Context is not reentrant") | 
					
						
							|  |  |  |         self.entered = deque() | 
					
						
							|  |  |  |         vars = [] | 
					
						
							|  |  |  |         try: | 
					
						
							| 
									
										
										
										
											2006-05-02 19:47:52 +00:00
										 |  |  |             for mgr in self.managers: | 
					
						
							| 
									
										
										
										
											2006-02-28 21:57:43 +00:00
										 |  |  |                 vars.append(mgr.__enter__()) | 
					
						
							|  |  |  |                 self.entered.appendleft(mgr) | 
					
						
							|  |  |  |         except: | 
					
						
							| 
									
										
										
										
											2006-03-10 02:28:35 +00:00
										 |  |  |             if not self.__exit__(*sys.exc_info()): | 
					
						
							|  |  |  |                 raise | 
					
						
							| 
									
										
										
										
											2006-02-28 21:57:43 +00:00
										 |  |  |         return vars | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __exit__(self, *exc_info): | 
					
						
							|  |  |  |         # Behave like nested with statements | 
					
						
							|  |  |  |         # first in, last out | 
					
						
							|  |  |  |         # New exceptions override old ones | 
					
						
							|  |  |  |         ex = exc_info | 
					
						
							|  |  |  |         for mgr in self.entered: | 
					
						
							|  |  |  |             try: | 
					
						
							| 
									
										
										
										
											2006-03-10 02:28:35 +00:00
										 |  |  |                 if mgr.__exit__(*ex): | 
					
						
							|  |  |  |                     ex = (None, None, None) | 
					
						
							| 
									
										
										
										
											2006-02-28 21:57:43 +00:00
										 |  |  |             except: | 
					
						
							|  |  |  |                 ex = sys.exc_info() | 
					
						
							|  |  |  |         self.entered = None | 
					
						
							|  |  |  |         if ex is not exc_info: | 
					
						
							|  |  |  |             raise ex[0], ex[1], ex[2] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class MockNested(Nested): | 
					
						
							| 
									
										
										
										
											2006-05-02 19:47:52 +00:00
										 |  |  |     def __init__(self, *managers): | 
					
						
							|  |  |  |         Nested.__init__(self, *managers) | 
					
						
							| 
									
										
										
										
											2006-02-28 18:44:41 +00:00
										 |  |  |         self.enter_called = False | 
					
						
							|  |  |  |         self.exit_called = False | 
					
						
							|  |  |  |         self.exit_args = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __enter__(self): | 
					
						
							|  |  |  |         self.enter_called = True | 
					
						
							| 
									
										
										
										
											2006-02-28 21:57:43 +00:00
										 |  |  |         return Nested.__enter__(self) | 
					
						
							| 
									
										
										
										
											2006-02-28 18:44:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def __exit__(self, *exc_info): | 
					
						
							|  |  |  |         self.exit_called = True | 
					
						
							|  |  |  |         self.exit_args = exc_info | 
					
						
							| 
									
										
										
										
											2006-02-28 21:57:43 +00:00
										 |  |  |         return Nested.__exit__(self, *exc_info) | 
					
						
							| 
									
										
										
										
											2006-02-28 18:44:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class FailureTestCase(unittest.TestCase): | 
					
						
							|  |  |  |     def testNameError(self): | 
					
						
							|  |  |  |         def fooNotDeclared(): | 
					
						
							|  |  |  |             with foo: pass | 
					
						
							|  |  |  |         self.assertRaises(NameError, fooNotDeclared) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def testEnterAttributeError(self): | 
					
						
							|  |  |  |         class LacksEnter(object): | 
					
						
							|  |  |  |             def __exit__(self, type, value, traceback): | 
					
						
							|  |  |  |                 pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def fooLacksEnter(): | 
					
						
							|  |  |  |             foo = LacksEnter() | 
					
						
							|  |  |  |             with foo: pass | 
					
						
							|  |  |  |         self.assertRaises(AttributeError, fooLacksEnter) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def testExitAttributeError(self): | 
					
						
							|  |  |  |         class LacksExit(object): | 
					
						
							|  |  |  |             def __enter__(self): | 
					
						
							|  |  |  |                 pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def fooLacksExit(): | 
					
						
							|  |  |  |             foo = LacksExit() | 
					
						
							|  |  |  |             with foo: pass | 
					
						
							|  |  |  |         self.assertRaises(AttributeError, fooLacksExit) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def assertRaisesSyntaxError(self, codestr): | 
					
						
							|  |  |  |         def shouldRaiseSyntaxError(s): | 
					
						
							|  |  |  |             compile(s, '', 'single') | 
					
						
							|  |  |  |         self.assertRaises(SyntaxError, shouldRaiseSyntaxError, codestr) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def testAssignmentToNoneError(self): | 
					
						
							|  |  |  |         self.assertRaisesSyntaxError('with mock as None:\n  pass') | 
					
						
							|  |  |  |         self.assertRaisesSyntaxError( | 
					
						
							|  |  |  |             'with mock as (None):\n' | 
					
						
							|  |  |  |             '  pass') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def testAssignmentToEmptyTupleError(self): | 
					
						
							|  |  |  |         self.assertRaisesSyntaxError( | 
					
						
							|  |  |  |             'with mock as ():\n' | 
					
						
							|  |  |  |             '  pass') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def testAssignmentToTupleOnlyContainingNoneError(self): | 
					
						
							|  |  |  |         self.assertRaisesSyntaxError('with mock as None,:\n  pass') | 
					
						
							|  |  |  |         self.assertRaisesSyntaxError( | 
					
						
							|  |  |  |             'with mock as (None,):\n' | 
					
						
							|  |  |  |             '  pass') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def testAssignmentToTupleContainingNoneError(self): | 
					
						
							|  |  |  |         self.assertRaisesSyntaxError( | 
					
						
							|  |  |  |             'with mock as (foo, None, bar):\n' | 
					
						
							|  |  |  |             '  pass') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def testEnterThrows(self): | 
					
						
							|  |  |  |         class EnterThrows(object): | 
					
						
							|  |  |  |             def __enter__(self): | 
					
						
							| 
									
										
										
										
											2006-05-02 19:47:52 +00:00
										 |  |  |                 raise RuntimeError("Enter threw") | 
					
						
							| 
									
										
										
										
											2006-02-28 18:44:41 +00:00
										 |  |  |             def __exit__(self, *args): | 
					
						
							|  |  |  |                 pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def shouldThrow(): | 
					
						
							|  |  |  |             ct = EnterThrows() | 
					
						
							|  |  |  |             self.foo = None | 
					
						
							|  |  |  |             with ct as self.foo: | 
					
						
							|  |  |  |                 pass | 
					
						
							|  |  |  |         self.assertRaises(RuntimeError, shouldThrow) | 
					
						
							|  |  |  |         self.assertEqual(self.foo, None) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def testExitThrows(self): | 
					
						
							|  |  |  |         class ExitThrows(object): | 
					
						
							|  |  |  |             def __enter__(self): | 
					
						
							|  |  |  |                 return | 
					
						
							|  |  |  |             def __exit__(self, *args): | 
					
						
							|  |  |  |                 raise RuntimeError(42) | 
					
						
							|  |  |  |         def shouldThrow(): | 
					
						
							|  |  |  |             with ExitThrows(): | 
					
						
							|  |  |  |                 pass | 
					
						
							|  |  |  |         self.assertRaises(RuntimeError, shouldThrow) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class ContextmanagerAssertionMixin(object): | 
					
						
							|  |  |  |     TEST_EXCEPTION = RuntimeError("test exception") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def assertInWithManagerInvariants(self, mock_manager): | 
					
						
							|  |  |  |         self.assertTrue(mock_manager.enter_called) | 
					
						
							|  |  |  |         self.assertFalse(mock_manager.exit_called) | 
					
						
							|  |  |  |         self.assertEqual(mock_manager.exit_args, None) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def assertAfterWithManagerInvariants(self, mock_manager, exit_args): | 
					
						
							|  |  |  |         self.assertTrue(mock_manager.enter_called) | 
					
						
							|  |  |  |         self.assertTrue(mock_manager.exit_called) | 
					
						
							|  |  |  |         self.assertEqual(mock_manager.exit_args, exit_args) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def assertAfterWithManagerInvariantsNoError(self, mock_manager): | 
					
						
							|  |  |  |         self.assertAfterWithManagerInvariants(mock_manager, | 
					
						
							|  |  |  |             (None, None, None)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def assertInWithGeneratorInvariants(self, mock_generator): | 
					
						
							|  |  |  |         self.assertTrue(mock_generator.yielded) | 
					
						
							|  |  |  |         self.assertFalse(mock_generator.stopped) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def assertAfterWithGeneratorInvariantsNoError(self, mock_generator): | 
					
						
							|  |  |  |         self.assertTrue(mock_generator.yielded) | 
					
						
							|  |  |  |         self.assertTrue(mock_generator.stopped) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def raiseTestException(self): | 
					
						
							|  |  |  |         raise self.TEST_EXCEPTION | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-05 01:53:27 +00:00
										 |  |  |     def assertAfterWithManagerInvariantsWithError(self, mock_manager, | 
					
						
							|  |  |  |                                                   exc_type=None): | 
					
						
							| 
									
										
										
										
											2006-02-28 18:44:41 +00:00
										 |  |  |         self.assertTrue(mock_manager.enter_called) | 
					
						
							|  |  |  |         self.assertTrue(mock_manager.exit_called) | 
					
						
							| 
									
										
										
										
											2010-02-05 01:53:27 +00:00
										 |  |  |         if exc_type is None: | 
					
						
							|  |  |  |             self.assertEqual(mock_manager.exit_args[1], self.TEST_EXCEPTION) | 
					
						
							|  |  |  |             exc_type = type(self.TEST_EXCEPTION) | 
					
						
							|  |  |  |         self.assertEqual(mock_manager.exit_args[0], exc_type) | 
					
						
							|  |  |  |         # Test the __exit__ arguments. Issue #7853 | 
					
						
							|  |  |  |         self.assertIsInstance(mock_manager.exit_args[1], exc_type) | 
					
						
							|  |  |  |         self.assertIsNot(mock_manager.exit_args[2], None) | 
					
						
							| 
									
										
										
										
											2006-02-28 18:44:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def assertAfterWithGeneratorInvariantsWithError(self, mock_generator): | 
					
						
							|  |  |  |         self.assertTrue(mock_generator.yielded) | 
					
						
							|  |  |  |         self.assertTrue(mock_generator.stopped) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class NonexceptionalTestCase(unittest.TestCase, ContextmanagerAssertionMixin): | 
					
						
							|  |  |  |     def testInlineGeneratorSyntax(self): | 
					
						
							|  |  |  |         with mock_contextmanager_generator(): | 
					
						
							|  |  |  |             pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def testUnboundGenerator(self): | 
					
						
							|  |  |  |         mock = mock_contextmanager_generator() | 
					
						
							|  |  |  |         with mock: | 
					
						
							|  |  |  |             pass | 
					
						
							|  |  |  |         self.assertAfterWithManagerInvariantsNoError(mock) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def testInlineGeneratorBoundSyntax(self): | 
					
						
							|  |  |  |         with mock_contextmanager_generator() as foo: | 
					
						
							|  |  |  |             self.assertInWithGeneratorInvariants(foo) | 
					
						
							|  |  |  |         # FIXME: In the future, we'll try to keep the bound names from leaking | 
					
						
							|  |  |  |         self.assertAfterWithGeneratorInvariantsNoError(foo) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def testInlineGeneratorBoundToExistingVariable(self): | 
					
						
							|  |  |  |         foo = None | 
					
						
							|  |  |  |         with mock_contextmanager_generator() as foo: | 
					
						
							|  |  |  |             self.assertInWithGeneratorInvariants(foo) | 
					
						
							|  |  |  |         self.assertAfterWithGeneratorInvariantsNoError(foo) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def testInlineGeneratorBoundToDottedVariable(self): | 
					
						
							|  |  |  |         with mock_contextmanager_generator() as self.foo: | 
					
						
							|  |  |  |             self.assertInWithGeneratorInvariants(self.foo) | 
					
						
							|  |  |  |         self.assertAfterWithGeneratorInvariantsNoError(self.foo) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def testBoundGenerator(self): | 
					
						
							|  |  |  |         mock = mock_contextmanager_generator() | 
					
						
							|  |  |  |         with mock as foo: | 
					
						
							|  |  |  |             self.assertInWithGeneratorInvariants(foo) | 
					
						
							|  |  |  |             self.assertInWithManagerInvariants(mock) | 
					
						
							|  |  |  |         self.assertAfterWithGeneratorInvariantsNoError(foo) | 
					
						
							|  |  |  |         self.assertAfterWithManagerInvariantsNoError(mock) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def testNestedSingleStatements(self): | 
					
						
							|  |  |  |         mock_a = mock_contextmanager_generator() | 
					
						
							|  |  |  |         with mock_a as foo: | 
					
						
							|  |  |  |             mock_b = mock_contextmanager_generator() | 
					
						
							|  |  |  |             with mock_b as bar: | 
					
						
							|  |  |  |                 self.assertInWithManagerInvariants(mock_a) | 
					
						
							|  |  |  |                 self.assertInWithManagerInvariants(mock_b) | 
					
						
							|  |  |  |                 self.assertInWithGeneratorInvariants(foo) | 
					
						
							|  |  |  |                 self.assertInWithGeneratorInvariants(bar) | 
					
						
							|  |  |  |             self.assertAfterWithManagerInvariantsNoError(mock_b) | 
					
						
							|  |  |  |             self.assertAfterWithGeneratorInvariantsNoError(bar) | 
					
						
							|  |  |  |             self.assertInWithManagerInvariants(mock_a) | 
					
						
							|  |  |  |             self.assertInWithGeneratorInvariants(foo) | 
					
						
							|  |  |  |         self.assertAfterWithManagerInvariantsNoError(mock_a) | 
					
						
							|  |  |  |         self.assertAfterWithGeneratorInvariantsNoError(foo) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class NestedNonexceptionalTestCase(unittest.TestCase, | 
					
						
							|  |  |  |     ContextmanagerAssertionMixin): | 
					
						
							|  |  |  |     def testSingleArgInlineGeneratorSyntax(self): | 
					
						
							| 
									
										
										
										
											2006-02-28 21:57:43 +00:00
										 |  |  |         with Nested(mock_contextmanager_generator()): | 
					
						
							| 
									
										
										
										
											2006-02-28 18:44:41 +00:00
										 |  |  |             pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def testSingleArgBoundToNonTuple(self): | 
					
						
							|  |  |  |         m = mock_contextmanager_generator() | 
					
						
							|  |  |  |         # This will bind all the arguments to nested() into a single list | 
					
						
							|  |  |  |         # assigned to foo. | 
					
						
							| 
									
										
										
										
											2006-02-28 21:57:43 +00:00
										 |  |  |         with Nested(m) as foo: | 
					
						
							| 
									
										
										
										
											2006-02-28 18:44:41 +00:00
										 |  |  |             self.assertInWithManagerInvariants(m) | 
					
						
							|  |  |  |         self.assertAfterWithManagerInvariantsNoError(m) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def testSingleArgBoundToSingleElementParenthesizedList(self): | 
					
						
							|  |  |  |         m = mock_contextmanager_generator() | 
					
						
							|  |  |  |         # This will bind all the arguments to nested() into a single list | 
					
						
							|  |  |  |         # assigned to foo. | 
					
						
							| 
									
										
										
										
											2006-02-28 21:57:43 +00:00
										 |  |  |         with Nested(m) as (foo): | 
					
						
							| 
									
										
										
										
											2006-02-28 18:44:41 +00:00
										 |  |  |             self.assertInWithManagerInvariants(m) | 
					
						
							|  |  |  |         self.assertAfterWithManagerInvariantsNoError(m) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def testSingleArgBoundToMultipleElementTupleError(self): | 
					
						
							|  |  |  |         def shouldThrowValueError(): | 
					
						
							| 
									
										
										
										
											2006-02-28 21:57:43 +00:00
										 |  |  |             with Nested(mock_contextmanager_generator()) as (foo, bar): | 
					
						
							| 
									
										
										
										
											2006-02-28 18:44:41 +00:00
										 |  |  |                 pass | 
					
						
							|  |  |  |         self.assertRaises(ValueError, shouldThrowValueError) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def testSingleArgUnbound(self): | 
					
						
							|  |  |  |         mock_contextmanager = mock_contextmanager_generator() | 
					
						
							|  |  |  |         mock_nested = MockNested(mock_contextmanager) | 
					
						
							|  |  |  |         with mock_nested: | 
					
						
							|  |  |  |             self.assertInWithManagerInvariants(mock_contextmanager) | 
					
						
							|  |  |  |             self.assertInWithManagerInvariants(mock_nested) | 
					
						
							|  |  |  |         self.assertAfterWithManagerInvariantsNoError(mock_contextmanager) | 
					
						
							|  |  |  |         self.assertAfterWithManagerInvariantsNoError(mock_nested) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def testMultipleArgUnbound(self): | 
					
						
							|  |  |  |         m = mock_contextmanager_generator() | 
					
						
							|  |  |  |         n = mock_contextmanager_generator() | 
					
						
							|  |  |  |         o = mock_contextmanager_generator() | 
					
						
							|  |  |  |         mock_nested = MockNested(m, n, o) | 
					
						
							|  |  |  |         with mock_nested: | 
					
						
							|  |  |  |             self.assertInWithManagerInvariants(m) | 
					
						
							|  |  |  |             self.assertInWithManagerInvariants(n) | 
					
						
							|  |  |  |             self.assertInWithManagerInvariants(o) | 
					
						
							|  |  |  |             self.assertInWithManagerInvariants(mock_nested) | 
					
						
							|  |  |  |         self.assertAfterWithManagerInvariantsNoError(m) | 
					
						
							|  |  |  |         self.assertAfterWithManagerInvariantsNoError(n) | 
					
						
							|  |  |  |         self.assertAfterWithManagerInvariantsNoError(o) | 
					
						
							|  |  |  |         self.assertAfterWithManagerInvariantsNoError(mock_nested) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def testMultipleArgBound(self): | 
					
						
							|  |  |  |         mock_nested = MockNested(mock_contextmanager_generator(), | 
					
						
							|  |  |  |             mock_contextmanager_generator(), mock_contextmanager_generator()) | 
					
						
							|  |  |  |         with mock_nested as (m, n, o): | 
					
						
							|  |  |  |             self.assertInWithGeneratorInvariants(m) | 
					
						
							|  |  |  |             self.assertInWithGeneratorInvariants(n) | 
					
						
							|  |  |  |             self.assertInWithGeneratorInvariants(o) | 
					
						
							|  |  |  |             self.assertInWithManagerInvariants(mock_nested) | 
					
						
							|  |  |  |         self.assertAfterWithGeneratorInvariantsNoError(m) | 
					
						
							|  |  |  |         self.assertAfterWithGeneratorInvariantsNoError(n) | 
					
						
							|  |  |  |         self.assertAfterWithGeneratorInvariantsNoError(o) | 
					
						
							|  |  |  |         self.assertAfterWithManagerInvariantsNoError(mock_nested) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class ExceptionalTestCase(unittest.TestCase, ContextmanagerAssertionMixin): | 
					
						
							|  |  |  |     def testSingleResource(self): | 
					
						
							|  |  |  |         cm = mock_contextmanager_generator() | 
					
						
							|  |  |  |         def shouldThrow(): | 
					
						
							|  |  |  |             with cm as self.resource: | 
					
						
							|  |  |  |                 self.assertInWithManagerInvariants(cm) | 
					
						
							|  |  |  |                 self.assertInWithGeneratorInvariants(self.resource) | 
					
						
							|  |  |  |                 self.raiseTestException() | 
					
						
							|  |  |  |         self.assertRaises(RuntimeError, shouldThrow) | 
					
						
							|  |  |  |         self.assertAfterWithManagerInvariantsWithError(cm) | 
					
						
							|  |  |  |         self.assertAfterWithGeneratorInvariantsWithError(self.resource) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-05 01:53:27 +00:00
										 |  |  |     def testExceptionNormalized(self): | 
					
						
							|  |  |  |         cm = mock_contextmanager_generator() | 
					
						
							|  |  |  |         def shouldThrow(): | 
					
						
							|  |  |  |             with cm as self.resource: | 
					
						
							|  |  |  |                 # Note this relies on the fact that 1 // 0 produces an exception | 
					
						
							|  |  |  |                 # that is not normalized immediately. | 
					
						
							|  |  |  |                 1 // 0 | 
					
						
							|  |  |  |         self.assertRaises(ZeroDivisionError, shouldThrow) | 
					
						
							|  |  |  |         self.assertAfterWithManagerInvariantsWithError(cm, ZeroDivisionError) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-28 18:44:41 +00:00
										 |  |  |     def testNestedSingleStatements(self): | 
					
						
							|  |  |  |         mock_a = mock_contextmanager_generator() | 
					
						
							|  |  |  |         mock_b = mock_contextmanager_generator() | 
					
						
							|  |  |  |         def shouldThrow(): | 
					
						
							|  |  |  |             with mock_a as self.foo: | 
					
						
							|  |  |  |                 with mock_b as self.bar: | 
					
						
							|  |  |  |                     self.assertInWithManagerInvariants(mock_a) | 
					
						
							|  |  |  |                     self.assertInWithManagerInvariants(mock_b) | 
					
						
							|  |  |  |                     self.assertInWithGeneratorInvariants(self.foo) | 
					
						
							|  |  |  |                     self.assertInWithGeneratorInvariants(self.bar) | 
					
						
							|  |  |  |                     self.raiseTestException() | 
					
						
							|  |  |  |         self.assertRaises(RuntimeError, shouldThrow) | 
					
						
							|  |  |  |         self.assertAfterWithManagerInvariantsWithError(mock_a) | 
					
						
							|  |  |  |         self.assertAfterWithManagerInvariantsWithError(mock_b) | 
					
						
							|  |  |  |         self.assertAfterWithGeneratorInvariantsWithError(self.foo) | 
					
						
							|  |  |  |         self.assertAfterWithGeneratorInvariantsWithError(self.bar) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def testMultipleResourcesInSingleStatement(self): | 
					
						
							|  |  |  |         cm_a = mock_contextmanager_generator() | 
					
						
							|  |  |  |         cm_b = mock_contextmanager_generator() | 
					
						
							|  |  |  |         mock_nested = MockNested(cm_a, cm_b) | 
					
						
							|  |  |  |         def shouldThrow(): | 
					
						
							|  |  |  |             with mock_nested as (self.resource_a, self.resource_b): | 
					
						
							|  |  |  |                 self.assertInWithManagerInvariants(cm_a) | 
					
						
							|  |  |  |                 self.assertInWithManagerInvariants(cm_b) | 
					
						
							|  |  |  |                 self.assertInWithManagerInvariants(mock_nested) | 
					
						
							|  |  |  |                 self.assertInWithGeneratorInvariants(self.resource_a) | 
					
						
							|  |  |  |                 self.assertInWithGeneratorInvariants(self.resource_b) | 
					
						
							|  |  |  |                 self.raiseTestException() | 
					
						
							|  |  |  |         self.assertRaises(RuntimeError, shouldThrow) | 
					
						
							|  |  |  |         self.assertAfterWithManagerInvariantsWithError(cm_a) | 
					
						
							|  |  |  |         self.assertAfterWithManagerInvariantsWithError(cm_b) | 
					
						
							|  |  |  |         self.assertAfterWithManagerInvariantsWithError(mock_nested) | 
					
						
							|  |  |  |         self.assertAfterWithGeneratorInvariantsWithError(self.resource_a) | 
					
						
							|  |  |  |         self.assertAfterWithGeneratorInvariantsWithError(self.resource_b) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def testNestedExceptionBeforeInnerStatement(self): | 
					
						
							|  |  |  |         mock_a = mock_contextmanager_generator() | 
					
						
							|  |  |  |         mock_b = mock_contextmanager_generator() | 
					
						
							|  |  |  |         self.bar = None | 
					
						
							|  |  |  |         def shouldThrow(): | 
					
						
							|  |  |  |             with mock_a as self.foo: | 
					
						
							|  |  |  |                 self.assertInWithManagerInvariants(mock_a) | 
					
						
							|  |  |  |                 self.assertInWithGeneratorInvariants(self.foo) | 
					
						
							|  |  |  |                 self.raiseTestException() | 
					
						
							|  |  |  |                 with mock_b as self.bar: | 
					
						
							|  |  |  |                     pass | 
					
						
							|  |  |  |         self.assertRaises(RuntimeError, shouldThrow) | 
					
						
							|  |  |  |         self.assertAfterWithManagerInvariantsWithError(mock_a) | 
					
						
							|  |  |  |         self.assertAfterWithGeneratorInvariantsWithError(self.foo) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # The inner statement stuff should never have been touched | 
					
						
							|  |  |  |         self.assertEqual(self.bar, None) | 
					
						
							|  |  |  |         self.assertFalse(mock_b.enter_called) | 
					
						
							|  |  |  |         self.assertFalse(mock_b.exit_called) | 
					
						
							|  |  |  |         self.assertEqual(mock_b.exit_args, None) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def testNestedExceptionAfterInnerStatement(self): | 
					
						
							|  |  |  |         mock_a = mock_contextmanager_generator() | 
					
						
							|  |  |  |         mock_b = mock_contextmanager_generator() | 
					
						
							|  |  |  |         def shouldThrow(): | 
					
						
							|  |  |  |             with mock_a as self.foo: | 
					
						
							|  |  |  |                 with mock_b as self.bar: | 
					
						
							|  |  |  |                     self.assertInWithManagerInvariants(mock_a) | 
					
						
							|  |  |  |                     self.assertInWithManagerInvariants(mock_b) | 
					
						
							|  |  |  |                     self.assertInWithGeneratorInvariants(self.foo) | 
					
						
							|  |  |  |                     self.assertInWithGeneratorInvariants(self.bar) | 
					
						
							|  |  |  |                 self.raiseTestException() | 
					
						
							|  |  |  |         self.assertRaises(RuntimeError, shouldThrow) | 
					
						
							|  |  |  |         self.assertAfterWithManagerInvariantsWithError(mock_a) | 
					
						
							|  |  |  |         self.assertAfterWithManagerInvariantsNoError(mock_b) | 
					
						
							|  |  |  |         self.assertAfterWithGeneratorInvariantsWithError(self.foo) | 
					
						
							|  |  |  |         self.assertAfterWithGeneratorInvariantsNoError(self.bar) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-03 20:05:05 +00:00
										 |  |  |     def testRaisedStopIteration1(self): | 
					
						
							| 
									
										
										
										
											2007-11-02 10:09:12 +00:00
										 |  |  |         # From bug 1462485 | 
					
						
							| 
									
										
										
										
											2006-05-03 13:02:47 +00:00
										 |  |  |         @contextmanager | 
					
						
							| 
									
										
										
										
											2006-04-03 20:05:05 +00:00
										 |  |  |         def cm(): | 
					
						
							|  |  |  |             yield | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def shouldThrow(): | 
					
						
							|  |  |  |             with cm(): | 
					
						
							|  |  |  |                 raise StopIteration("from with") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertRaises(StopIteration, shouldThrow) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def testRaisedStopIteration2(self): | 
					
						
							| 
									
										
										
										
											2007-11-02 10:09:12 +00:00
										 |  |  |         # From bug 1462485 | 
					
						
							| 
									
										
										
										
											2006-05-02 19:47:52 +00:00
										 |  |  |         class cm(object): | 
					
						
							| 
									
										
										
										
											2006-04-03 20:05:05 +00:00
										 |  |  |             def __enter__(self): | 
					
						
							|  |  |  |                 pass | 
					
						
							|  |  |  |             def __exit__(self, type, value, traceback): | 
					
						
							|  |  |  |                 pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def shouldThrow(): | 
					
						
							|  |  |  |             with cm(): | 
					
						
							|  |  |  |                 raise StopIteration("from with") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertRaises(StopIteration, shouldThrow) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-11-02 10:09:12 +00:00
										 |  |  |     def testRaisedStopIteration3(self): | 
					
						
							|  |  |  |         # Another variant where the exception hasn't been instantiated | 
					
						
							|  |  |  |         # From bug 1705170 | 
					
						
							|  |  |  |         @contextmanager | 
					
						
							|  |  |  |         def cm(): | 
					
						
							|  |  |  |             yield | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def shouldThrow(): | 
					
						
							|  |  |  |             with cm(): | 
					
						
							|  |  |  |                 raise iter([]).next() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertRaises(StopIteration, shouldThrow) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-03 20:05:05 +00:00
										 |  |  |     def testRaisedGeneratorExit1(self): | 
					
						
							| 
									
										
										
										
											2007-11-02 10:09:12 +00:00
										 |  |  |         # From bug 1462485 | 
					
						
							| 
									
										
										
										
											2006-05-03 13:02:47 +00:00
										 |  |  |         @contextmanager | 
					
						
							| 
									
										
										
										
											2006-04-03 20:05:05 +00:00
										 |  |  |         def cm(): | 
					
						
							|  |  |  |             yield | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def shouldThrow(): | 
					
						
							|  |  |  |             with cm(): | 
					
						
							|  |  |  |                 raise GeneratorExit("from with") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertRaises(GeneratorExit, shouldThrow) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def testRaisedGeneratorExit2(self): | 
					
						
							| 
									
										
										
										
											2007-11-02 10:09:12 +00:00
										 |  |  |         # From bug 1462485 | 
					
						
							| 
									
										
										
										
											2006-04-03 20:05:05 +00:00
										 |  |  |         class cm (object): | 
					
						
							|  |  |  |             def __enter__(self): | 
					
						
							|  |  |  |                 pass | 
					
						
							|  |  |  |             def __exit__(self, type, value, traceback): | 
					
						
							|  |  |  |                 pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def shouldThrow(): | 
					
						
							|  |  |  |             with cm(): | 
					
						
							|  |  |  |                 raise GeneratorExit("from with") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertRaises(GeneratorExit, shouldThrow) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-10 23:22:49 +00:00
										 |  |  |     def testErrorsInBool(self): | 
					
						
							|  |  |  |         # issue4589: __exit__ return code may raise an exception | 
					
						
							|  |  |  |         # when looking at its truth value. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         class cm(object): | 
					
						
							|  |  |  |             def __init__(self, bool_conversion): | 
					
						
							|  |  |  |                 class Bool: | 
					
						
							|  |  |  |                     def __nonzero__(self): | 
					
						
							|  |  |  |                         return bool_conversion() | 
					
						
							|  |  |  |                 self.exit_result = Bool() | 
					
						
							|  |  |  |             def __enter__(self): | 
					
						
							|  |  |  |                 return 3 | 
					
						
							|  |  |  |             def __exit__(self, a, b, c): | 
					
						
							|  |  |  |                 return self.exit_result | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def trueAsBool(): | 
					
						
							|  |  |  |             with cm(lambda: True): | 
					
						
							|  |  |  |                 self.fail("Should NOT see this") | 
					
						
							|  |  |  |         trueAsBool() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def falseAsBool(): | 
					
						
							|  |  |  |             with cm(lambda: False): | 
					
						
							|  |  |  |                 self.fail("Should raise") | 
					
						
							|  |  |  |         self.assertRaises(AssertionError, falseAsBool) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def failAsBool(): | 
					
						
							| 
									
										
										
										
											2010-02-03 05:37:26 +00:00
										 |  |  |             with cm(lambda: 1 // 0): | 
					
						
							| 
									
										
										
										
											2008-12-10 23:22:49 +00:00
										 |  |  |                 self.fail("Should NOT see this") | 
					
						
							|  |  |  |         self.assertRaises(ZeroDivisionError, failAsBool) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-28 18:44:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | class NonLocalFlowControlTestCase(unittest.TestCase): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def testWithBreak(self): | 
					
						
							|  |  |  |         counter = 0 | 
					
						
							|  |  |  |         while True: | 
					
						
							|  |  |  |             counter += 1 | 
					
						
							|  |  |  |             with mock_contextmanager_generator(): | 
					
						
							|  |  |  |                 counter += 10 | 
					
						
							|  |  |  |                 break | 
					
						
							|  |  |  |             counter += 100 # Not reached | 
					
						
							|  |  |  |         self.assertEqual(counter, 11) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def testWithContinue(self): | 
					
						
							|  |  |  |         counter = 0 | 
					
						
							|  |  |  |         while True: | 
					
						
							|  |  |  |             counter += 1 | 
					
						
							|  |  |  |             if counter > 2: | 
					
						
							|  |  |  |                 break | 
					
						
							|  |  |  |             with mock_contextmanager_generator(): | 
					
						
							|  |  |  |                 counter += 10 | 
					
						
							|  |  |  |                 continue | 
					
						
							|  |  |  |             counter += 100 # Not reached | 
					
						
							|  |  |  |         self.assertEqual(counter, 12) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def testWithReturn(self): | 
					
						
							|  |  |  |         def foo(): | 
					
						
							|  |  |  |             counter = 0 | 
					
						
							|  |  |  |             while True: | 
					
						
							|  |  |  |                 counter += 1 | 
					
						
							|  |  |  |                 with mock_contextmanager_generator(): | 
					
						
							|  |  |  |                     counter += 10 | 
					
						
							|  |  |  |                     return counter | 
					
						
							|  |  |  |                 counter += 100 # Not reached | 
					
						
							|  |  |  |         self.assertEqual(foo(), 11) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def testWithYield(self): | 
					
						
							|  |  |  |         def gen(): | 
					
						
							|  |  |  |             with mock_contextmanager_generator(): | 
					
						
							|  |  |  |                 yield 12 | 
					
						
							|  |  |  |                 yield 13 | 
					
						
							|  |  |  |         x = list(gen()) | 
					
						
							|  |  |  |         self.assertEqual(x, [12, 13]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def testWithRaise(self): | 
					
						
							|  |  |  |         counter = 0 | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             counter += 1 | 
					
						
							|  |  |  |             with mock_contextmanager_generator(): | 
					
						
							|  |  |  |                 counter += 10 | 
					
						
							|  |  |  |                 raise RuntimeError | 
					
						
							|  |  |  |             counter += 100 # Not reached | 
					
						
							|  |  |  |         except RuntimeError: | 
					
						
							|  |  |  |             self.assertEqual(counter, 11) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             self.fail("Didn't raise RuntimeError") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class AssignmentTargetTestCase(unittest.TestCase): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def testSingleComplexTarget(self): | 
					
						
							|  |  |  |         targets = {1: [0, 1, 2]} | 
					
						
							|  |  |  |         with mock_contextmanager_generator() as targets[1][0]: | 
					
						
							|  |  |  |             self.assertEqual(targets.keys(), [1]) | 
					
						
							|  |  |  |             self.assertEqual(targets[1][0].__class__, MockResource) | 
					
						
							|  |  |  |         with mock_contextmanager_generator() as targets.values()[0][1]: | 
					
						
							|  |  |  |             self.assertEqual(targets.keys(), [1]) | 
					
						
							|  |  |  |             self.assertEqual(targets[1][1].__class__, MockResource) | 
					
						
							|  |  |  |         with mock_contextmanager_generator() as targets[2]: | 
					
						
							|  |  |  |             keys = targets.keys() | 
					
						
							|  |  |  |             keys.sort() | 
					
						
							|  |  |  |             self.assertEqual(keys, [1, 2]) | 
					
						
							|  |  |  |         class C: pass | 
					
						
							|  |  |  |         blah = C() | 
					
						
							|  |  |  |         with mock_contextmanager_generator() as blah.foo: | 
					
						
							|  |  |  |             self.assertEqual(hasattr(blah, "foo"), True) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def testMultipleComplexTargets(self): | 
					
						
							|  |  |  |         class C: | 
					
						
							|  |  |  |             def __enter__(self): return 1, 2, 3 | 
					
						
							| 
									
										
										
										
											2006-03-10 02:28:35 +00:00
										 |  |  |             def __exit__(self, t, v, tb): pass | 
					
						
							| 
									
										
										
										
											2006-02-28 18:44:41 +00:00
										 |  |  |         targets = {1: [0, 1, 2]} | 
					
						
							|  |  |  |         with C() as (targets[1][0], targets[1][1], targets[1][2]): | 
					
						
							|  |  |  |             self.assertEqual(targets, {1: [1, 2, 3]}) | 
					
						
							|  |  |  |         with C() as (targets.values()[0][2], targets.values()[0][1], targets.values()[0][0]): | 
					
						
							|  |  |  |             self.assertEqual(targets, {1: [3, 2, 1]}) | 
					
						
							|  |  |  |         with C() as (targets[1], targets[2], targets[3]): | 
					
						
							|  |  |  |             self.assertEqual(targets, {1: 1, 2: 2, 3: 3}) | 
					
						
							|  |  |  |         class B: pass | 
					
						
							|  |  |  |         blah = B() | 
					
						
							|  |  |  |         with C() as (blah.one, blah.two, blah.three): | 
					
						
							|  |  |  |             self.assertEqual(blah.one, 1) | 
					
						
							|  |  |  |             self.assertEqual(blah.two, 2) | 
					
						
							|  |  |  |             self.assertEqual(blah.three, 3) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-28 21:57:43 +00:00
										 |  |  | class ExitSwallowsExceptionTestCase(unittest.TestCase): | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-03-10 02:28:35 +00:00
										 |  |  |     def testExitTrueSwallowsException(self): | 
					
						
							|  |  |  |         class AfricanSwallow: | 
					
						
							| 
									
										
										
										
											2006-02-28 21:57:43 +00:00
										 |  |  |             def __enter__(self): pass | 
					
						
							| 
									
										
										
										
											2006-03-10 02:28:35 +00:00
										 |  |  |             def __exit__(self, t, v, tb): return True | 
					
						
							| 
									
										
										
										
											2006-02-28 21:57:43 +00:00
										 |  |  |         try: | 
					
						
							| 
									
										
										
										
											2006-03-10 02:28:35 +00:00
										 |  |  |             with AfricanSwallow(): | 
					
						
							| 
									
										
										
										
											2010-02-03 05:37:26 +00:00
										 |  |  |                 1 // 0 | 
					
						
							| 
									
										
										
										
											2006-02-28 21:57:43 +00:00
										 |  |  |         except ZeroDivisionError: | 
					
						
							|  |  |  |             self.fail("ZeroDivisionError should have been swallowed") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-03-10 02:28:35 +00:00
										 |  |  |     def testExitFalseDoesntSwallowException(self): | 
					
						
							|  |  |  |         class EuropeanSwallow: | 
					
						
							|  |  |  |             def __enter__(self): pass | 
					
						
							|  |  |  |             def __exit__(self, t, v, tb): return False | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             with EuropeanSwallow(): | 
					
						
							| 
									
										
										
										
											2010-02-03 05:37:26 +00:00
										 |  |  |                 1 // 0 | 
					
						
							| 
									
										
										
										
											2006-03-10 02:28:35 +00:00
										 |  |  |         except ZeroDivisionError: | 
					
						
							|  |  |  |             pass | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             self.fail("ZeroDivisionError should have been raised") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-28 21:57:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-25 21:02:56 +00:00
										 |  |  | class NestedWith(unittest.TestCase): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     class Dummy(object): | 
					
						
							|  |  |  |         def __init__(self, value=None, gobble=False): | 
					
						
							|  |  |  |             if value is None: | 
					
						
							|  |  |  |                 value = self | 
					
						
							|  |  |  |             self.value = value | 
					
						
							|  |  |  |             self.gobble = gobble | 
					
						
							|  |  |  |             self.enter_called = False | 
					
						
							|  |  |  |             self.exit_called = False | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def __enter__(self): | 
					
						
							|  |  |  |             self.enter_called = True | 
					
						
							|  |  |  |             return self.value | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def __exit__(self, *exc_info): | 
					
						
							|  |  |  |             self.exit_called = True | 
					
						
							|  |  |  |             self.exc_info = exc_info | 
					
						
							|  |  |  |             if self.gobble: | 
					
						
							|  |  |  |                 return True | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-04 10:10:41 +00:00
										 |  |  |     class InitRaises(object): | 
					
						
							| 
									
										
										
										
											2009-05-25 21:02:56 +00:00
										 |  |  |         def __init__(self): raise RuntimeError() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     class EnterRaises(object): | 
					
						
							|  |  |  |         def __enter__(self): raise RuntimeError() | 
					
						
							|  |  |  |         def __exit__(self, *exc_info): pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     class ExitRaises(object): | 
					
						
							|  |  |  |         def __enter__(self): pass | 
					
						
							|  |  |  |         def __exit__(self, *exc_info): raise RuntimeError() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def testNoExceptions(self): | 
					
						
							|  |  |  |         with self.Dummy() as a, self.Dummy() as b: | 
					
						
							|  |  |  |             self.assertTrue(a.enter_called) | 
					
						
							|  |  |  |             self.assertTrue(b.enter_called) | 
					
						
							|  |  |  |         self.assertTrue(a.exit_called) | 
					
						
							|  |  |  |         self.assertTrue(b.exit_called) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def testExceptionInExprList(self): | 
					
						
							|  |  |  |         try: | 
					
						
							| 
									
										
										
										
											2009-06-04 10:10:41 +00:00
										 |  |  |             with self.Dummy() as a, self.InitRaises(): | 
					
						
							| 
									
										
										
										
											2009-05-25 21:02:56 +00:00
										 |  |  |                 pass | 
					
						
							|  |  |  |         except: | 
					
						
							|  |  |  |             pass | 
					
						
							|  |  |  |         self.assertTrue(a.enter_called) | 
					
						
							|  |  |  |         self.assertTrue(a.exit_called) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def testExceptionInEnter(self): | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             with self.Dummy() as a, self.EnterRaises(): | 
					
						
							|  |  |  |                 self.fail('body of bad with executed') | 
					
						
							|  |  |  |         except RuntimeError: | 
					
						
							|  |  |  |             pass | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             self.fail('RuntimeError not reraised') | 
					
						
							|  |  |  |         self.assertTrue(a.enter_called) | 
					
						
							|  |  |  |         self.assertTrue(a.exit_called) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def testExceptionInExit(self): | 
					
						
							|  |  |  |         body_executed = False | 
					
						
							|  |  |  |         with self.Dummy(gobble=True) as a, self.ExitRaises(): | 
					
						
							|  |  |  |             body_executed = True | 
					
						
							|  |  |  |         self.assertTrue(a.enter_called) | 
					
						
							|  |  |  |         self.assertTrue(a.exit_called) | 
					
						
							| 
									
										
										
										
											2009-06-19 22:09:17 +00:00
										 |  |  |         self.assertTrue(body_executed) | 
					
						
							| 
									
										
										
										
											2009-05-25 21:02:56 +00:00
										 |  |  |         self.assertNotEqual(a.exc_info[0], None) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def testEnterReturnsTuple(self): | 
					
						
							|  |  |  |         with self.Dummy(value=(1,2)) as (a1, a2), \ | 
					
						
							|  |  |  |              self.Dummy(value=(10, 20)) as (b1, b2): | 
					
						
							|  |  |  |             self.assertEquals(1, a1) | 
					
						
							|  |  |  |             self.assertEquals(2, a2) | 
					
						
							|  |  |  |             self.assertEquals(10, b1) | 
					
						
							|  |  |  |             self.assertEquals(20, b2) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-28 18:44:41 +00:00
										 |  |  | def test_main(): | 
					
						
							|  |  |  |     run_unittest(FailureTestCase, NonexceptionalTestCase, | 
					
						
							|  |  |  |                  NestedNonexceptionalTestCase, ExceptionalTestCase, | 
					
						
							|  |  |  |                  NonLocalFlowControlTestCase, | 
					
						
							| 
									
										
										
										
											2006-02-28 21:57:43 +00:00
										 |  |  |                  AssignmentTargetTestCase, | 
					
						
							| 
									
										
										
										
											2009-05-25 21:02:56 +00:00
										 |  |  |                  ExitSwallowsExceptionTestCase, | 
					
						
							|  |  |  |                  NestedWith) | 
					
						
							| 
									
										
										
										
											2006-02-28 18:44:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if __name__ == '__main__': | 
					
						
							|  |  |  |     test_main() |