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 7import sys 8import unittest 9from collections import deque 10from contextlib import _GeneratorContextManager, contextmanager 11 12 13class MockContextManager(_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 31def mock_contextmanager(func): 32 def helper(*args, **kwds): 33 return MockContextManager(func, args, kwds) 34 return helper 35 36 37class MockResource(object): 38 def __init__(self): 39 self.yielded = False 40 self.stopped = False 41 42 43@mock_contextmanager 44def mock_contextmanager_generator(): 45 mock = MockResource() 46 try: 47 mock.yielded = True 48 yield mock 49 finally: 50 mock.stopped = True 51 52 53class Nested(object): 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 89class MockNested(Nested): 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 106class FailureTestCase(unittest.TestCase): 107 def testNameError(self): 108 def fooNotDeclared(): 109 with foo: pass 110 self.assertRaises(NameError, fooNotDeclared) 111 112 def testEnterAttributeError1(self): 113 class LacksEnter(object): 114 def __exit__(self, type, value, traceback): 115 pass 116 117 def fooLacksEnter(): 118 foo = LacksEnter() 119 with foo: pass 120 self.assertRaisesRegex(AttributeError, '__enter__', fooLacksEnter) 121 122 def testEnterAttributeError2(self): 123 class LacksEnterAndExit(object): 124 pass 125 126 def fooLacksEnterAndExit(): 127 foo = LacksEnterAndExit() 128 with foo: pass 129 self.assertRaisesRegex(AttributeError, '__enter__', fooLacksEnterAndExit) 130 131 def testExitAttributeError(self): 132 class LacksExit(object): 133 def __enter__(self): 134 pass 135 136 def fooLacksExit(): 137 foo = LacksExit() 138 with foo: pass 139 self.assertRaisesRegex(AttributeError, '__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 EnterThrows(object): 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 ExitThrows(object): 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 189class ContextmanagerAssertionMixin(object): 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 236class NonexceptionalTestCase(unittest.TestCase, ContextmanagerAssertionMixin): 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 289class NestedNonexceptionalTestCase(unittest.TestCase, 290 ContextmanagerAssertionMixin): 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 355class ExceptionalTestCase(ContextmanagerAssertionMixin, unittest.TestCase): 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 cm(object): 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 cm (object): 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 cm(object): 524 def __init__(self, bool_conversion): 525 class Bool: 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 550class NonLocalFlowControlTestCase(unittest.TestCase): 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 607class AssignmentTargetTestCase(unittest.TestCase): 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 C: 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 C: 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 B: 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 645class ExitSwallowsExceptionTestCase(unittest.TestCase): 646 647 def testExitTrueSwallowsException(self): 648 class AfricanSwallow: 649 def __enter__(self): pass 650 def __exit__(self, t, v, tb): return True 651 try: 652 with AfricanSwallow(): 653 1/0 654 except ZeroDivisionError: 655 self.fail("ZeroDivisionError should have been swallowed") 656 657 def testExitFalseDoesntSwallowException(self): 658 class EuropeanSwallow: 659 def __enter__(self): pass 660 def __exit__(self, t, v, tb): return False 661 try: 662 with EuropeanSwallow(): 663 1/0 664 except ZeroDivisionError: 665 pass 666 else: 667 self.fail("ZeroDivisionError should have been raised") 668 669 670class NestedWith(unittest.TestCase): 671 672 class Dummy(object): 673 def __init__(self, value=None, gobble=False): 674 if value is None: 675 value = self 676 self.value = value 677 self.gobble = gobble 678 self.enter_called = False 679 self.exit_called = False 680 681 def __enter__(self): 682 self.enter_called = True 683 return self.value 684 685 def __exit__(self, *exc_info): 686 self.exit_called = True 687 self.exc_info = exc_info 688 if self.gobble: 689 return True 690 691 class InitRaises(object): 692 def __init__(self): raise RuntimeError() 693 694 class EnterRaises(object): 695 def __enter__(self): raise RuntimeError() 696 def __exit__(self, *exc_info): pass 697 698 class ExitRaises(object): 699 def __enter__(self): pass 700 def __exit__(self, *exc_info): raise RuntimeError() 701 702 def testNoExceptions(self): 703 with self.Dummy() as a, self.Dummy() as b: 704 self.assertTrue(a.enter_called) 705 self.assertTrue(b.enter_called) 706 self.assertTrue(a.exit_called) 707 self.assertTrue(b.exit_called) 708 709 def testExceptionInExprList(self): 710 try: 711 with self.Dummy() as a, self.InitRaises(): 712 pass 713 except: 714 pass 715 self.assertTrue(a.enter_called) 716 self.assertTrue(a.exit_called) 717 718 def testExceptionInEnter(self): 719 try: 720 with self.Dummy() as a, self.EnterRaises(): 721 self.fail('body of bad with executed') 722 except RuntimeError: 723 pass 724 else: 725 self.fail('RuntimeError not reraised') 726 self.assertTrue(a.enter_called) 727 self.assertTrue(a.exit_called) 728 729 def testExceptionInExit(self): 730 body_executed = False 731 with self.Dummy(gobble=True) as a, self.ExitRaises(): 732 body_executed = True 733 self.assertTrue(a.enter_called) 734 self.assertTrue(a.exit_called) 735 self.assertTrue(body_executed) 736 self.assertNotEqual(a.exc_info[0], None) 737 738 def testEnterReturnsTuple(self): 739 with self.Dummy(value=(1,2)) as (a1, a2), \ 740 self.Dummy(value=(10, 20)) as (b1, b2): 741 self.assertEqual(1, a1) 742 self.assertEqual(2, a2) 743 self.assertEqual(10, b1) 744 self.assertEqual(20, b2) 745 746if __name__ == '__main__': 747 unittest.main() 748