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