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 11 12 13 class 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 31 def mock_contextmanager(func): 32 def helper(*args, **kwds): 33 return MockContextManager(func, args, kwds) 34 return helper 35 36 37 class MockResource(object): 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 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 89 class 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 106 class 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 189 class 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 236 class 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 289 class 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 355 class 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.assertWarnsRegex(DeprecationWarning, "StopIteration"): 462 self.assertRaises(StopIteration, 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 self.assertRaises(StopIteration, shouldThrow) 477 478 def testRaisedStopIteration3(self): 479 # Another variant where the exception hasn't been instantiated 480 # From bug 1705170 481 @contextmanager 482 def cm(): 483 yield 484 485 def shouldThrow(): 486 with cm(): 487 raise next(iter([])) 488 489 with self.assertWarnsRegex(DeprecationWarning, "StopIteration"): 490 self.assertRaises(StopIteration, shouldThrow) 491 492 def testRaisedGeneratorExit1(self): 493 # From bug 1462485 494 @contextmanager 495 def cm(): 496 yield 497 498 def shouldThrow(): 499 with cm(): 500 raise GeneratorExit("from with") 501 502 self.assertRaises(GeneratorExit, shouldThrow) 503 504 def testRaisedGeneratorExit2(self): 505 # From bug 1462485 506 class cm (object): 507 def __enter__(self): 508 pass 509 def __exit__(self, type, value, traceback): 510 pass 511 512 def shouldThrow(): 513 with cm(): 514 raise GeneratorExit("from with") 515 516 self.assertRaises(GeneratorExit, shouldThrow) 517 518 def testErrorsInBool(self): 519 # issue4589: __exit__ return code may raise an exception 520 # when looking at its truth value. 521 522 class cm(object): 523 def __init__(self, bool_conversion): 524 class Bool: 525 def __bool__(self): 526 return bool_conversion() 527 self.exit_result = Bool() 528 def __enter__(self): 529 return 3 530 def __exit__(self, a, b, c): 531 return self.exit_result 532 533 def trueAsBool(): 534 with cm(lambda: True): 535 self.fail("Should NOT see this") 536 trueAsBool() 537 538 def falseAsBool(): 539 with cm(lambda: False): 540 self.fail("Should raise") 541 self.assertRaises(AssertionError, falseAsBool) 542 543 def failAsBool(): 544 with cm(lambda: 1//0): 545 self.fail("Should NOT see this") 546 self.assertRaises(ZeroDivisionError, failAsBool) 547 548 549 class NonLocalFlowControlTestCase(unittest.TestCase): 550 551 def testWithBreak(self): 552 counter = 0 553 while True: 554 counter += 1 555 with mock_contextmanager_generator(): 556 counter += 10 557 break 558 counter += 100 # Not reached 559 self.assertEqual(counter, 11) 560 561 def testWithContinue(self): 562 counter = 0 563 while True: 564 counter += 1 565 if counter > 2: 566 break 567 with mock_contextmanager_generator(): 568 counter += 10 569 continue 570 counter += 100 # Not reached 571 self.assertEqual(counter, 12) 572 573 def testWithReturn(self): 574 def foo(): 575 counter = 0 576 while True: 577 counter += 1 578 with mock_contextmanager_generator(): 579 counter += 10 580 return counter 581 counter += 100 # Not reached 582 self.assertEqual(foo(), 11) 583 584 def testWithYield(self): 585 def gen(): 586 with mock_contextmanager_generator(): 587 yield 12 588 yield 13 589 x = list(gen()) 590 self.assertEqual(x, [12, 13]) 591 592 def testWithRaise(self): 593 counter = 0 594 try: 595 counter += 1 596 with mock_contextmanager_generator(): 597 counter += 10 598 raise RuntimeError 599 counter += 100 # Not reached 600 except RuntimeError: 601 self.assertEqual(counter, 11) 602 else: 603 self.fail("Didn't raise RuntimeError") 604 605 606 class AssignmentTargetTestCase(unittest.TestCase): 607 608 def testSingleComplexTarget(self): 609 targets = {1: [0, 1, 2]} 610 with mock_contextmanager_generator() as targets[1][0]: 611 self.assertEqual(list(targets.keys()), [1]) 612 self.assertEqual(targets[1][0].__class__, MockResource) 613 with mock_contextmanager_generator() as list(targets.values())[0][1]: 614 self.assertEqual(list(targets.keys()), [1]) 615 self.assertEqual(targets[1][1].__class__, MockResource) 616 with mock_contextmanager_generator() as targets[2]: 617 keys = list(targets.keys()) 618 keys.sort() 619 self.assertEqual(keys, [1, 2]) 620 class C: pass 621 blah = C() 622 with mock_contextmanager_generator() as blah.foo: 623 self.assertEqual(hasattr(blah, "foo"), True) 624 625 def testMultipleComplexTargets(self): 626 class C: 627 def __enter__(self): return 1, 2, 3 628 def __exit__(self, t, v, tb): pass 629 targets = {1: [0, 1, 2]} 630 with C() as (targets[1][0], targets[1][1], targets[1][2]): 631 self.assertEqual(targets, {1: [1, 2, 3]}) 632 with C() as (list(targets.values())[0][2], list(targets.values())[0][1], list(targets.values())[0][0]): 633 self.assertEqual(targets, {1: [3, 2, 1]}) 634 with C() as (targets[1], targets[2], targets[3]): 635 self.assertEqual(targets, {1: 1, 2: 2, 3: 3}) 636 class B: pass 637 blah = B() 638 with C() as (blah.one, blah.two, blah.three): 639 self.assertEqual(blah.one, 1) 640 self.assertEqual(blah.two, 2) 641 self.assertEqual(blah.three, 3) 642 643 644 class ExitSwallowsExceptionTestCase(unittest.TestCase): 645 646 def testExitTrueSwallowsException(self): 647 class AfricanSwallow: 648 def __enter__(self): pass 649 def __exit__(self, t, v, tb): return True 650 try: 651 with AfricanSwallow(): 652 1/0 653 except ZeroDivisionError: 654 self.fail("ZeroDivisionError should have been swallowed") 655 656 def testExitFalseDoesntSwallowException(self): 657 class EuropeanSwallow: 658 def __enter__(self): pass 659 def __exit__(self, t, v, tb): return False 660 try: 661 with EuropeanSwallow(): 662 1/0 663 except ZeroDivisionError: 664 pass 665 else: 666 self.fail("ZeroDivisionError should have been raised") 667 668 669 class NestedWith(unittest.TestCase): 670 671 class Dummy(object): 672 def __init__(self, value=None, gobble=False): 673 if value is None: 674 value = self 675 self.value = value 676 self.gobble = gobble 677 self.enter_called = False 678 self.exit_called = False 679 680 def __enter__(self): 681 self.enter_called = True 682 return self.value 683 684 def __exit__(self, *exc_info): 685 self.exit_called = True 686 self.exc_info = exc_info 687 if self.gobble: 688 return True 689 690 class InitRaises(object): 691 def __init__(self): raise RuntimeError() 692 693 class EnterRaises(object): 694 def __enter__(self): raise RuntimeError() 695 def __exit__(self, *exc_info): pass 696 697 class ExitRaises(object): 698 def __enter__(self): pass 699 def __exit__(self, *exc_info): raise RuntimeError() 700 701 def testNoExceptions(self): 702 with self.Dummy() as a, self.Dummy() as b: 703 self.assertTrue(a.enter_called) 704 self.assertTrue(b.enter_called) 705 self.assertTrue(a.exit_called) 706 self.assertTrue(b.exit_called) 707 708 def testExceptionInExprList(self): 709 try: 710 with self.Dummy() as a, self.InitRaises(): 711 pass 712 except: 713 pass 714 self.assertTrue(a.enter_called) 715 self.assertTrue(a.exit_called) 716 717 def testExceptionInEnter(self): 718 try: 719 with self.Dummy() as a, self.EnterRaises(): 720 self.fail('body of bad with executed') 721 except RuntimeError: 722 pass 723 else: 724 self.fail('RuntimeError not reraised') 725 self.assertTrue(a.enter_called) 726 self.assertTrue(a.exit_called) 727 728 def testExceptionInExit(self): 729 body_executed = False 730 with self.Dummy(gobble=True) as a, self.ExitRaises(): 731 body_executed = True 732 self.assertTrue(a.enter_called) 733 self.assertTrue(a.exit_called) 734 self.assertTrue(body_executed) 735 self.assertNotEqual(a.exc_info[0], None) 736 737 def testEnterReturnsTuple(self): 738 with self.Dummy(value=(1,2)) as (a1, a2), \ 739 self.Dummy(value=(10, 20)) as (b1, b2): 740 self.assertEqual(1, a1) 741 self.assertEqual(2, a2) 742 self.assertEqual(10, b1) 743 self.assertEqual(20, b2) 744 745 if __name__ == '__main__': 746 unittest.main() 747