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