(root)/
Python-3.11.7/
Lib/
test/
test_with.py
       1  """Unit tests for the with statement specified in PEP 343."""
       2  
       3  
       4  __author__ = "Mike Bland"
       5  __email__ = "mbland at acm dot org"
       6  
       7  import sys
       8  import unittest
       9  from collections import deque
      10  from contextlib import _GeneratorContextManager, contextmanager, nullcontext
      11  
      12  
      13  class ESC[4;38;5;81mMockContextManager(ESC[4;38;5;149m_GeneratorContextManager):
      14      def __init__(self, *args):
      15          super().__init__(*args)
      16          self.enter_called = False
      17          self.exit_called = False
      18          self.exit_args = None
      19  
      20      def __enter__(self):
      21          self.enter_called = True
      22          return _GeneratorContextManager.__enter__(self)
      23  
      24      def __exit__(self, type, value, traceback):
      25          self.exit_called = True
      26          self.exit_args = (type, value, traceback)
      27          return _GeneratorContextManager.__exit__(self, type,
      28                                                   value, traceback)
      29  
      30  
      31  def mock_contextmanager(func):
      32      def helper(*args, **kwds):
      33          return MockContextManager(func, args, kwds)
      34      return helper
      35  
      36  
      37  class ESC[4;38;5;81mMockResource(ESC[4;38;5;149mobject):
      38      def __init__(self):
      39          self.yielded = False
      40          self.stopped = False
      41  
      42  
      43  @mock_contextmanager
      44  def mock_contextmanager_generator():
      45      mock = MockResource()
      46      try:
      47          mock.yielded = True
      48          yield mock
      49      finally:
      50          mock.stopped = True
      51  
      52  
      53  class ESC[4;38;5;81mNested(ESC[4;38;5;149mobject):
      54  
      55      def __init__(self, *managers):
      56          self.managers = managers
      57          self.entered = None
      58  
      59      def __enter__(self):
      60          if self.entered is not None:
      61              raise RuntimeError("Context is not reentrant")
      62          self.entered = deque()
      63          vars = []
      64          try:
      65              for mgr in self.managers:
      66                  vars.append(mgr.__enter__())
      67                  self.entered.appendleft(mgr)
      68          except:
      69              if not self.__exit__(*sys.exc_info()):
      70                  raise
      71          return vars
      72  
      73      def __exit__(self, *exc_info):
      74          # Behave like nested with statements
      75          # first in, last out
      76          # New exceptions override old ones
      77          ex = exc_info
      78          for mgr in self.entered:
      79              try:
      80                  if mgr.__exit__(*ex):
      81                      ex = (None, None, None)
      82              except:
      83                  ex = sys.exc_info()
      84          self.entered = None
      85          if ex is not exc_info:
      86              raise ex[0](ex[1]).with_traceback(ex[2])
      87  
      88  
      89  class ESC[4;38;5;81mMockNested(ESC[4;38;5;149mNested):
      90      def __init__(self, *managers):
      91          Nested.__init__(self, *managers)
      92          self.enter_called = False
      93          self.exit_called = False
      94          self.exit_args = None
      95  
      96      def __enter__(self):
      97          self.enter_called = True
      98          return Nested.__enter__(self)
      99  
     100      def __exit__(self, *exc_info):
     101          self.exit_called = True
     102          self.exit_args = exc_info
     103          return Nested.__exit__(self, *exc_info)
     104  
     105  
     106  class ESC[4;38;5;81mFailureTestCase(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
     107      def testNameError(self):
     108          def fooNotDeclared():
     109              with foo: pass
     110          self.assertRaises(NameError, fooNotDeclared)
     111  
     112      def testEnterAttributeError1(self):
     113          class ESC[4;38;5;81mLacksEnter(ESC[4;38;5;149mobject):
     114              def __exit__(self, type, value, traceback):
     115                  pass
     116  
     117          def fooLacksEnter():
     118              foo = LacksEnter()
     119              with foo: pass
     120          self.assertRaisesRegex(TypeError, 'the context manager', fooLacksEnter)
     121  
     122      def testEnterAttributeError2(self):
     123          class ESC[4;38;5;81mLacksEnterAndExit(ESC[4;38;5;149mobject):
     124              pass
     125  
     126          def fooLacksEnterAndExit():
     127              foo = LacksEnterAndExit()
     128              with foo: pass
     129          self.assertRaisesRegex(TypeError, 'the context manager', fooLacksEnterAndExit)
     130  
     131      def testExitAttributeError(self):
     132          class ESC[4;38;5;81mLacksExit(ESC[4;38;5;149mobject):
     133              def __enter__(self):
     134                  pass
     135  
     136          def fooLacksExit():
     137              foo = LacksExit()
     138              with foo: pass
     139          self.assertRaisesRegex(TypeError, 'the context manager.*__exit__', fooLacksExit)
     140  
     141      def assertRaisesSyntaxError(self, codestr):
     142          def shouldRaiseSyntaxError(s):
     143              compile(s, '', 'single')
     144          self.assertRaises(SyntaxError, shouldRaiseSyntaxError, codestr)
     145  
     146      def testAssignmentToNoneError(self):
     147          self.assertRaisesSyntaxError('with mock as None:\n  pass')
     148          self.assertRaisesSyntaxError(
     149              'with mock as (None):\n'
     150              '  pass')
     151  
     152      def testAssignmentToTupleOnlyContainingNoneError(self):
     153          self.assertRaisesSyntaxError('with mock as None,:\n  pass')
     154          self.assertRaisesSyntaxError(
     155              'with mock as (None,):\n'
     156              '  pass')
     157  
     158      def testAssignmentToTupleContainingNoneError(self):
     159          self.assertRaisesSyntaxError(
     160              'with mock as (foo, None, bar):\n'
     161              '  pass')
     162  
     163      def testEnterThrows(self):
     164          class ESC[4;38;5;81mEnterThrows(ESC[4;38;5;149mobject):
     165              def __enter__(self):
     166                  raise RuntimeError("Enter threw")
     167              def __exit__(self, *args):
     168                  pass
     169  
     170          def shouldThrow():
     171              ct = EnterThrows()
     172              self.foo = None
     173              with ct as self.foo:
     174                  pass
     175          self.assertRaises(RuntimeError, shouldThrow)
     176          self.assertEqual(self.foo, None)
     177  
     178      def testExitThrows(self):
     179          class ESC[4;38;5;81mExitThrows(ESC[4;38;5;149mobject):
     180              def __enter__(self):
     181                  return
     182              def __exit__(self, *args):
     183                  raise RuntimeError(42)
     184          def shouldThrow():
     185              with ExitThrows():
     186                  pass
     187          self.assertRaises(RuntimeError, shouldThrow)
     188  
     189  class ESC[4;38;5;81mContextmanagerAssertionMixin(ESC[4;38;5;149mobject):
     190  
     191      def setUp(self):
     192          self.TEST_EXCEPTION = RuntimeError("test exception")
     193  
     194      def assertInWithManagerInvariants(self, mock_manager):
     195          self.assertTrue(mock_manager.enter_called)
     196          self.assertFalse(mock_manager.exit_called)
     197          self.assertEqual(mock_manager.exit_args, None)
     198  
     199      def assertAfterWithManagerInvariants(self, mock_manager, exit_args):
     200          self.assertTrue(mock_manager.enter_called)
     201          self.assertTrue(mock_manager.exit_called)
     202          self.assertEqual(mock_manager.exit_args, exit_args)
     203  
     204      def assertAfterWithManagerInvariantsNoError(self, mock_manager):
     205          self.assertAfterWithManagerInvariants(mock_manager,
     206              (None, None, None))
     207  
     208      def assertInWithGeneratorInvariants(self, mock_generator):
     209          self.assertTrue(mock_generator.yielded)
     210          self.assertFalse(mock_generator.stopped)
     211  
     212      def assertAfterWithGeneratorInvariantsNoError(self, mock_generator):
     213          self.assertTrue(mock_generator.yielded)
     214          self.assertTrue(mock_generator.stopped)
     215  
     216      def raiseTestException(self):
     217          raise self.TEST_EXCEPTION
     218  
     219      def assertAfterWithManagerInvariantsWithError(self, mock_manager,
     220                                                    exc_type=None):
     221          self.assertTrue(mock_manager.enter_called)
     222          self.assertTrue(mock_manager.exit_called)
     223          if exc_type is None:
     224              self.assertEqual(mock_manager.exit_args[1], self.TEST_EXCEPTION)
     225              exc_type = type(self.TEST_EXCEPTION)
     226          self.assertEqual(mock_manager.exit_args[0], exc_type)
     227          # Test the __exit__ arguments. Issue #7853
     228          self.assertIsInstance(mock_manager.exit_args[1], exc_type)
     229          self.assertIsNot(mock_manager.exit_args[2], None)
     230  
     231      def assertAfterWithGeneratorInvariantsWithError(self, mock_generator):
     232          self.assertTrue(mock_generator.yielded)
     233          self.assertTrue(mock_generator.stopped)
     234  
     235  
     236  class ESC[4;38;5;81mNonexceptionalTestCase(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase, ESC[4;38;5;149mContextmanagerAssertionMixin):
     237      def testInlineGeneratorSyntax(self):
     238          with mock_contextmanager_generator():
     239              pass
     240  
     241      def testUnboundGenerator(self):
     242          mock = mock_contextmanager_generator()
     243          with mock:
     244              pass
     245          self.assertAfterWithManagerInvariantsNoError(mock)
     246  
     247      def testInlineGeneratorBoundSyntax(self):
     248          with mock_contextmanager_generator() as foo:
     249              self.assertInWithGeneratorInvariants(foo)
     250          # FIXME: In the future, we'll try to keep the bound names from leaking
     251          self.assertAfterWithGeneratorInvariantsNoError(foo)
     252  
     253      def testInlineGeneratorBoundToExistingVariable(self):
     254          foo = None
     255          with mock_contextmanager_generator() as foo:
     256              self.assertInWithGeneratorInvariants(foo)
     257          self.assertAfterWithGeneratorInvariantsNoError(foo)
     258  
     259      def testInlineGeneratorBoundToDottedVariable(self):
     260          with mock_contextmanager_generator() as self.foo:
     261              self.assertInWithGeneratorInvariants(self.foo)
     262          self.assertAfterWithGeneratorInvariantsNoError(self.foo)
     263  
     264      def testBoundGenerator(self):
     265          mock = mock_contextmanager_generator()
     266          with mock as foo:
     267              self.assertInWithGeneratorInvariants(foo)
     268              self.assertInWithManagerInvariants(mock)
     269          self.assertAfterWithGeneratorInvariantsNoError(foo)
     270          self.assertAfterWithManagerInvariantsNoError(mock)
     271  
     272      def testNestedSingleStatements(self):
     273          mock_a = mock_contextmanager_generator()
     274          with mock_a as foo:
     275              mock_b = mock_contextmanager_generator()
     276              with mock_b as bar:
     277                  self.assertInWithManagerInvariants(mock_a)
     278                  self.assertInWithManagerInvariants(mock_b)
     279                  self.assertInWithGeneratorInvariants(foo)
     280                  self.assertInWithGeneratorInvariants(bar)
     281              self.assertAfterWithManagerInvariantsNoError(mock_b)
     282              self.assertAfterWithGeneratorInvariantsNoError(bar)
     283              self.assertInWithManagerInvariants(mock_a)
     284              self.assertInWithGeneratorInvariants(foo)
     285          self.assertAfterWithManagerInvariantsNoError(mock_a)
     286          self.assertAfterWithGeneratorInvariantsNoError(foo)
     287  
     288  
     289  class ESC[4;38;5;81mNestedNonexceptionalTestCase(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase,
     290      ESC[4;38;5;149mContextmanagerAssertionMixin):
     291      def testSingleArgInlineGeneratorSyntax(self):
     292          with Nested(mock_contextmanager_generator()):
     293              pass
     294  
     295      def testSingleArgBoundToNonTuple(self):
     296          m = mock_contextmanager_generator()
     297          # This will bind all the arguments to nested() into a single list
     298          # assigned to foo.
     299          with Nested(m) as foo:
     300              self.assertInWithManagerInvariants(m)
     301          self.assertAfterWithManagerInvariantsNoError(m)
     302  
     303      def testSingleArgBoundToSingleElementParenthesizedList(self):
     304          m = mock_contextmanager_generator()
     305          # This will bind all the arguments to nested() into a single list
     306          # assigned to foo.
     307          with Nested(m) as (foo):
     308              self.assertInWithManagerInvariants(m)
     309          self.assertAfterWithManagerInvariantsNoError(m)
     310  
     311      def testSingleArgBoundToMultipleElementTupleError(self):
     312          def shouldThrowValueError():
     313              with Nested(mock_contextmanager_generator()) as (foo, bar):
     314                  pass
     315          self.assertRaises(ValueError, shouldThrowValueError)
     316  
     317      def testSingleArgUnbound(self):
     318          mock_contextmanager = mock_contextmanager_generator()
     319          mock_nested = MockNested(mock_contextmanager)
     320          with mock_nested:
     321              self.assertInWithManagerInvariants(mock_contextmanager)
     322              self.assertInWithManagerInvariants(mock_nested)
     323          self.assertAfterWithManagerInvariantsNoError(mock_contextmanager)
     324          self.assertAfterWithManagerInvariantsNoError(mock_nested)
     325  
     326      def testMultipleArgUnbound(self):
     327          m = mock_contextmanager_generator()
     328          n = mock_contextmanager_generator()
     329          o = mock_contextmanager_generator()
     330          mock_nested = MockNested(m, n, o)
     331          with mock_nested:
     332              self.assertInWithManagerInvariants(m)
     333              self.assertInWithManagerInvariants(n)
     334              self.assertInWithManagerInvariants(o)
     335              self.assertInWithManagerInvariants(mock_nested)
     336          self.assertAfterWithManagerInvariantsNoError(m)
     337          self.assertAfterWithManagerInvariantsNoError(n)
     338          self.assertAfterWithManagerInvariantsNoError(o)
     339          self.assertAfterWithManagerInvariantsNoError(mock_nested)
     340  
     341      def testMultipleArgBound(self):
     342          mock_nested = MockNested(mock_contextmanager_generator(),
     343              mock_contextmanager_generator(), mock_contextmanager_generator())
     344          with mock_nested as (m, n, o):
     345              self.assertInWithGeneratorInvariants(m)
     346              self.assertInWithGeneratorInvariants(n)
     347              self.assertInWithGeneratorInvariants(o)
     348              self.assertInWithManagerInvariants(mock_nested)
     349          self.assertAfterWithGeneratorInvariantsNoError(m)
     350          self.assertAfterWithGeneratorInvariantsNoError(n)
     351          self.assertAfterWithGeneratorInvariantsNoError(o)
     352          self.assertAfterWithManagerInvariantsNoError(mock_nested)
     353  
     354  
     355  class ESC[4;38;5;81mExceptionalTestCase(ESC[4;38;5;149mContextmanagerAssertionMixin, ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
     356      def testSingleResource(self):
     357          cm = mock_contextmanager_generator()
     358          def shouldThrow():
     359              with cm as self.resource:
     360                  self.assertInWithManagerInvariants(cm)
     361                  self.assertInWithGeneratorInvariants(self.resource)
     362                  self.raiseTestException()
     363          self.assertRaises(RuntimeError, shouldThrow)
     364          self.assertAfterWithManagerInvariantsWithError(cm)
     365          self.assertAfterWithGeneratorInvariantsWithError(self.resource)
     366  
     367      def testExceptionNormalized(self):
     368          cm = mock_contextmanager_generator()
     369          def shouldThrow():
     370              with cm as self.resource:
     371                  # Note this relies on the fact that 1 // 0 produces an exception
     372                  # that is not normalized immediately.
     373                  1 // 0
     374          self.assertRaises(ZeroDivisionError, shouldThrow)
     375          self.assertAfterWithManagerInvariantsWithError(cm, ZeroDivisionError)
     376  
     377      def testNestedSingleStatements(self):
     378          mock_a = mock_contextmanager_generator()
     379          mock_b = mock_contextmanager_generator()
     380          def shouldThrow():
     381              with mock_a as self.foo:
     382                  with mock_b as self.bar:
     383                      self.assertInWithManagerInvariants(mock_a)
     384                      self.assertInWithManagerInvariants(mock_b)
     385                      self.assertInWithGeneratorInvariants(self.foo)
     386                      self.assertInWithGeneratorInvariants(self.bar)
     387                      self.raiseTestException()
     388          self.assertRaises(RuntimeError, shouldThrow)
     389          self.assertAfterWithManagerInvariantsWithError(mock_a)
     390          self.assertAfterWithManagerInvariantsWithError(mock_b)
     391          self.assertAfterWithGeneratorInvariantsWithError(self.foo)
     392          self.assertAfterWithGeneratorInvariantsWithError(self.bar)
     393  
     394      def testMultipleResourcesInSingleStatement(self):
     395          cm_a = mock_contextmanager_generator()
     396          cm_b = mock_contextmanager_generator()
     397          mock_nested = MockNested(cm_a, cm_b)
     398          def shouldThrow():
     399              with mock_nested as (self.resource_a, self.resource_b):
     400                  self.assertInWithManagerInvariants(cm_a)
     401                  self.assertInWithManagerInvariants(cm_b)
     402                  self.assertInWithManagerInvariants(mock_nested)
     403                  self.assertInWithGeneratorInvariants(self.resource_a)
     404                  self.assertInWithGeneratorInvariants(self.resource_b)
     405                  self.raiseTestException()
     406          self.assertRaises(RuntimeError, shouldThrow)
     407          self.assertAfterWithManagerInvariantsWithError(cm_a)
     408          self.assertAfterWithManagerInvariantsWithError(cm_b)
     409          self.assertAfterWithManagerInvariantsWithError(mock_nested)
     410          self.assertAfterWithGeneratorInvariantsWithError(self.resource_a)
     411          self.assertAfterWithGeneratorInvariantsWithError(self.resource_b)
     412  
     413      def testNestedExceptionBeforeInnerStatement(self):
     414          mock_a = mock_contextmanager_generator()
     415          mock_b = mock_contextmanager_generator()
     416          self.bar = None
     417          def shouldThrow():
     418              with mock_a as self.foo:
     419                  self.assertInWithManagerInvariants(mock_a)
     420                  self.assertInWithGeneratorInvariants(self.foo)
     421                  self.raiseTestException()
     422                  with mock_b as self.bar:
     423                      pass
     424          self.assertRaises(RuntimeError, shouldThrow)
     425          self.assertAfterWithManagerInvariantsWithError(mock_a)
     426          self.assertAfterWithGeneratorInvariantsWithError(self.foo)
     427  
     428          # The inner statement stuff should never have been touched
     429          self.assertEqual(self.bar, None)
     430          self.assertFalse(mock_b.enter_called)
     431          self.assertFalse(mock_b.exit_called)
     432          self.assertEqual(mock_b.exit_args, None)
     433  
     434      def testNestedExceptionAfterInnerStatement(self):
     435          mock_a = mock_contextmanager_generator()
     436          mock_b = mock_contextmanager_generator()
     437          def shouldThrow():
     438              with mock_a as self.foo:
     439                  with mock_b as self.bar:
     440                      self.assertInWithManagerInvariants(mock_a)
     441                      self.assertInWithManagerInvariants(mock_b)
     442                      self.assertInWithGeneratorInvariants(self.foo)
     443                      self.assertInWithGeneratorInvariants(self.bar)
     444                  self.raiseTestException()
     445          self.assertRaises(RuntimeError, shouldThrow)
     446          self.assertAfterWithManagerInvariantsWithError(mock_a)
     447          self.assertAfterWithManagerInvariantsNoError(mock_b)
     448          self.assertAfterWithGeneratorInvariantsWithError(self.foo)
     449          self.assertAfterWithGeneratorInvariantsNoError(self.bar)
     450  
     451      def testRaisedStopIteration1(self):
     452          # From bug 1462485
     453          @contextmanager
     454          def cm():
     455              yield
     456  
     457          def shouldThrow():
     458              with cm():
     459                  raise StopIteration("from with")
     460  
     461          with self.assertRaisesRegex(StopIteration, 'from with'):
     462              shouldThrow()
     463  
     464      def testRaisedStopIteration2(self):
     465          # From bug 1462485
     466          class ESC[4;38;5;81mcm(ESC[4;38;5;149mobject):
     467              def __enter__(self):
     468                  pass
     469              def __exit__(self, type, value, traceback):
     470                  pass
     471  
     472          def shouldThrow():
     473              with cm():
     474                  raise StopIteration("from with")
     475  
     476          with self.assertRaisesRegex(StopIteration, 'from with'):
     477              shouldThrow()
     478  
     479      def testRaisedStopIteration3(self):
     480          # Another variant where the exception hasn't been instantiated
     481          # From bug 1705170
     482          @contextmanager
     483          def cm():
     484              yield
     485  
     486          def shouldThrow():
     487              with cm():
     488                  raise next(iter([]))
     489  
     490          with self.assertRaises(StopIteration):
     491              shouldThrow()
     492  
     493      def testRaisedGeneratorExit1(self):
     494          # From bug 1462485
     495          @contextmanager
     496          def cm():
     497              yield
     498  
     499          def shouldThrow():
     500              with cm():
     501                  raise GeneratorExit("from with")
     502  
     503          self.assertRaises(GeneratorExit, shouldThrow)
     504  
     505      def testRaisedGeneratorExit2(self):
     506          # From bug 1462485
     507          class ESC[4;38;5;81mcm (ESC[4;38;5;149mobject):
     508              def __enter__(self):
     509                  pass
     510              def __exit__(self, type, value, traceback):
     511                  pass
     512  
     513          def shouldThrow():
     514              with cm():
     515                  raise GeneratorExit("from with")
     516  
     517          self.assertRaises(GeneratorExit, shouldThrow)
     518  
     519      def testErrorsInBool(self):
     520          # issue4589: __exit__ return code may raise an exception
     521          # when looking at its truth value.
     522  
     523          class ESC[4;38;5;81mcm(ESC[4;38;5;149mobject):
     524              def __init__(self, bool_conversion):
     525                  class ESC[4;38;5;81mBool:
     526                      def __bool__(self):
     527                          return bool_conversion()
     528                  self.exit_result = Bool()
     529              def __enter__(self):
     530                  return 3
     531              def __exit__(self, a, b, c):
     532                  return self.exit_result
     533  
     534          def trueAsBool():
     535              with cm(lambda: True):
     536                  self.fail("Should NOT see this")
     537          trueAsBool()
     538  
     539          def falseAsBool():
     540              with cm(lambda: False):
     541                  self.fail("Should raise")
     542          self.assertRaises(AssertionError, falseAsBool)
     543  
     544          def failAsBool():
     545              with cm(lambda: 1//0):
     546                  self.fail("Should NOT see this")
     547          self.assertRaises(ZeroDivisionError, failAsBool)
     548  
     549  
     550  class ESC[4;38;5;81mNonLocalFlowControlTestCase(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
     551  
     552      def testWithBreak(self):
     553          counter = 0
     554          while True:
     555              counter += 1
     556              with mock_contextmanager_generator():
     557                  counter += 10
     558                  break
     559              counter += 100 # Not reached
     560          self.assertEqual(counter, 11)
     561  
     562      def testWithContinue(self):
     563          counter = 0
     564          while True:
     565              counter += 1
     566              if counter > 2:
     567                  break
     568              with mock_contextmanager_generator():
     569                  counter += 10
     570                  continue
     571              counter += 100 # Not reached
     572          self.assertEqual(counter, 12)
     573  
     574      def testWithReturn(self):
     575          def foo():
     576              counter = 0
     577              while True:
     578                  counter += 1
     579                  with mock_contextmanager_generator():
     580                      counter += 10
     581                      return counter
     582                  counter += 100 # Not reached
     583          self.assertEqual(foo(), 11)
     584  
     585      def testWithYield(self):
     586          def gen():
     587              with mock_contextmanager_generator():
     588                  yield 12
     589                  yield 13
     590          x = list(gen())
     591          self.assertEqual(x, [12, 13])
     592  
     593      def testWithRaise(self):
     594          counter = 0
     595          try:
     596              counter += 1
     597              with mock_contextmanager_generator():
     598                  counter += 10
     599                  raise RuntimeError
     600              counter += 100 # Not reached
     601          except RuntimeError:
     602              self.assertEqual(counter, 11)
     603          else:
     604              self.fail("Didn't raise RuntimeError")
     605  
     606  
     607  class ESC[4;38;5;81mAssignmentTargetTestCase(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
     608  
     609      def testSingleComplexTarget(self):
     610          targets = {1: [0, 1, 2]}
     611          with mock_contextmanager_generator() as targets[1][0]:
     612              self.assertEqual(list(targets.keys()), [1])
     613              self.assertEqual(targets[1][0].__class__, MockResource)
     614          with mock_contextmanager_generator() as list(targets.values())[0][1]:
     615              self.assertEqual(list(targets.keys()), [1])
     616              self.assertEqual(targets[1][1].__class__, MockResource)
     617          with mock_contextmanager_generator() as targets[2]:
     618              keys = list(targets.keys())
     619              keys.sort()
     620              self.assertEqual(keys, [1, 2])
     621          class ESC[4;38;5;81mC: pass
     622          blah = C()
     623          with mock_contextmanager_generator() as blah.foo:
     624              self.assertEqual(hasattr(blah, "foo"), True)
     625  
     626      def testMultipleComplexTargets(self):
     627          class ESC[4;38;5;81mC:
     628              def __enter__(self): return 1, 2, 3
     629              def __exit__(self, t, v, tb): pass
     630          targets = {1: [0, 1, 2]}
     631          with C() as (targets[1][0], targets[1][1], targets[1][2]):
     632              self.assertEqual(targets, {1: [1, 2, 3]})
     633          with C() as (list(targets.values())[0][2], list(targets.values())[0][1], list(targets.values())[0][0]):
     634              self.assertEqual(targets, {1: [3, 2, 1]})
     635          with C() as (targets[1], targets[2], targets[3]):
     636              self.assertEqual(targets, {1: 1, 2: 2, 3: 3})
     637          class ESC[4;38;5;81mB: pass
     638          blah = B()
     639          with C() as (blah.one, blah.two, blah.three):
     640              self.assertEqual(blah.one, 1)
     641              self.assertEqual(blah.two, 2)
     642              self.assertEqual(blah.three, 3)
     643  
     644      def testWithExtendedTargets(self):
     645          with nullcontext(range(1, 5)) as (a, *b, c):
     646              self.assertEqual(a, 1)
     647              self.assertEqual(b, [2, 3])
     648              self.assertEqual(c, 4)
     649  
     650  
     651  class ESC[4;38;5;81mExitSwallowsExceptionTestCase(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
     652  
     653      def testExitTrueSwallowsException(self):
     654          class ESC[4;38;5;81mAfricanSwallow:
     655              def __enter__(self): pass
     656              def __exit__(self, t, v, tb): return True
     657          try:
     658              with AfricanSwallow():
     659                  1/0
     660          except ZeroDivisionError:
     661              self.fail("ZeroDivisionError should have been swallowed")
     662  
     663      def testExitFalseDoesntSwallowException(self):
     664          class ESC[4;38;5;81mEuropeanSwallow:
     665              def __enter__(self): pass
     666              def __exit__(self, t, v, tb): return False
     667          try:
     668              with EuropeanSwallow():
     669                  1/0
     670          except ZeroDivisionError:
     671              pass
     672          else:
     673              self.fail("ZeroDivisionError should have been raised")
     674  
     675  
     676  class ESC[4;38;5;81mNestedWith(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
     677  
     678      class ESC[4;38;5;81mDummy(ESC[4;38;5;149mobject):
     679          def __init__(self, value=None, gobble=False):
     680              if value is None:
     681                  value = self
     682              self.value = value
     683              self.gobble = gobble
     684              self.enter_called = False
     685              self.exit_called = False
     686  
     687          def __enter__(self):
     688              self.enter_called = True
     689              return self.value
     690  
     691          def __exit__(self, *exc_info):
     692              self.exit_called = True
     693              self.exc_info = exc_info
     694              if self.gobble:
     695                  return True
     696  
     697      class ESC[4;38;5;81mInitRaises(ESC[4;38;5;149mobject):
     698          def __init__(self): raise RuntimeError()
     699  
     700      class ESC[4;38;5;81mEnterRaises(ESC[4;38;5;149mobject):
     701          def __enter__(self): raise RuntimeError()
     702          def __exit__(self, *exc_info): pass
     703  
     704      class ESC[4;38;5;81mExitRaises(ESC[4;38;5;149mobject):
     705          def __enter__(self): pass
     706          def __exit__(self, *exc_info): raise RuntimeError()
     707  
     708      def testNoExceptions(self):
     709          with self.Dummy() as a, self.Dummy() as b:
     710              self.assertTrue(a.enter_called)
     711              self.assertTrue(b.enter_called)
     712          self.assertTrue(a.exit_called)
     713          self.assertTrue(b.exit_called)
     714  
     715      def testExceptionInExprList(self):
     716          try:
     717              with self.Dummy() as a, self.InitRaises():
     718                  pass
     719          except:
     720              pass
     721          self.assertTrue(a.enter_called)
     722          self.assertTrue(a.exit_called)
     723  
     724      def testExceptionInEnter(self):
     725          try:
     726              with self.Dummy() as a, self.EnterRaises():
     727                  self.fail('body of bad with executed')
     728          except RuntimeError:
     729              pass
     730          else:
     731              self.fail('RuntimeError not reraised')
     732          self.assertTrue(a.enter_called)
     733          self.assertTrue(a.exit_called)
     734  
     735      def testExceptionInExit(self):
     736          body_executed = False
     737          with self.Dummy(gobble=True) as a, self.ExitRaises():
     738              body_executed = True
     739          self.assertTrue(a.enter_called)
     740          self.assertTrue(a.exit_called)
     741          self.assertTrue(body_executed)
     742          self.assertNotEqual(a.exc_info[0], None)
     743  
     744      def testEnterReturnsTuple(self):
     745          with self.Dummy(value=(1,2)) as (a1, a2), \
     746               self.Dummy(value=(10, 20)) as (b1, b2):
     747              self.assertEqual(1, a1)
     748              self.assertEqual(2, a2)
     749              self.assertEqual(10, b1)
     750              self.assertEqual(20, b2)
     751  
     752  if __name__ == '__main__':
     753      unittest.main()