blob: 48e00f43e6c7559c03866475615028311d9d2c6d [file] [log] [blame]
Tim Peters400cbc32006-02-28 18:44:41 +00001#!/usr/bin/env python
2
3"""Unit tests for the with statement specified in PEP 343."""
4
Thomas Wouters34aa7ba2006-02-28 19:02:24 +00005from __future__ import with_statement
6
Tim Peters400cbc32006-02-28 18:44:41 +00007__author__ = "Mike Bland"
8__email__ = "mbland at acm dot org"
9
Guido van Rossum1a5e21e2006-02-28 21:57:43 +000010import sys
Tim Peters400cbc32006-02-28 18:44:41 +000011import unittest
Guido van Rossum1a5e21e2006-02-28 21:57:43 +000012from collections import deque
13from contextlib import GeneratorContextManager, contextmanager
Tim Peters400cbc32006-02-28 18:44:41 +000014from test.test_support import run_unittest
15
16
17class MockContextManager(GeneratorContextManager):
18 def __init__(self, gen):
19 GeneratorContextManager.__init__(self, gen)
20 self.context_called = False
21 self.enter_called = False
22 self.exit_called = False
23 self.exit_args = None
24
25 def __context__(self):
26 self.context_called = True
27 return GeneratorContextManager.__context__(self)
28
29 def __enter__(self):
30 self.enter_called = True
31 return GeneratorContextManager.__enter__(self)
32
33 def __exit__(self, type, value, traceback):
34 self.exit_called = True
35 self.exit_args = (type, value, traceback)
36 return GeneratorContextManager.__exit__(self, type, value, traceback)
37
38
39def mock_contextmanager(func):
40 def helper(*args, **kwds):
41 return MockContextManager(func(*args, **kwds))
42 return helper
43
44
45class MockResource(object):
46 def __init__(self):
47 self.yielded = False
48 self.stopped = False
49
50
51@mock_contextmanager
52def mock_contextmanager_generator():
53 mock = MockResource()
54 try:
55 mock.yielded = True
56 yield mock
57 finally:
58 mock.stopped = True
59
60
Guido van Rossum1a5e21e2006-02-28 21:57:43 +000061class Nested(object):
62
Tim Peters400cbc32006-02-28 18:44:41 +000063 def __init__(self, *contexts):
Guido van Rossum1a5e21e2006-02-28 21:57:43 +000064 self.contexts = contexts
65 self.entered = None
66
67 def __context__(self):
68 return self
69
70 def __enter__(self):
71 if self.entered is not None:
72 raise RuntimeError("Context is not reentrant")
73 self.entered = deque()
74 vars = []
75 try:
76 for context in self.contexts:
77 mgr = context.__context__()
78 vars.append(mgr.__enter__())
79 self.entered.appendleft(mgr)
80 except:
Guido van Rossumf6694362006-03-10 02:28:35 +000081 if not self.__exit__(*sys.exc_info()):
82 raise
Guido van Rossum1a5e21e2006-02-28 21:57:43 +000083 return vars
84
85 def __exit__(self, *exc_info):
86 # Behave like nested with statements
87 # first in, last out
88 # New exceptions override old ones
89 ex = exc_info
90 for mgr in self.entered:
91 try:
Guido van Rossumf6694362006-03-10 02:28:35 +000092 if mgr.__exit__(*ex):
93 ex = (None, None, None)
Guido van Rossum1a5e21e2006-02-28 21:57:43 +000094 except:
95 ex = sys.exc_info()
96 self.entered = None
97 if ex is not exc_info:
98 raise ex[0], ex[1], ex[2]
99
100
101class MockNested(Nested):
102 def __init__(self, *contexts):
103 Nested.__init__(self, *contexts)
Tim Peters400cbc32006-02-28 18:44:41 +0000104 self.context_called = False
105 self.enter_called = False
106 self.exit_called = False
107 self.exit_args = None
108
109 def __context__(self):
110 self.context_called = True
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000111 return Nested.__context__(self)
Tim Peters400cbc32006-02-28 18:44:41 +0000112
113 def __enter__(self):
114 self.enter_called = True
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000115 return Nested.__enter__(self)
Tim Peters400cbc32006-02-28 18:44:41 +0000116
117 def __exit__(self, *exc_info):
118 self.exit_called = True
119 self.exit_args = exc_info
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000120 return Nested.__exit__(self, *exc_info)
Tim Peters400cbc32006-02-28 18:44:41 +0000121
122
123class FailureTestCase(unittest.TestCase):
124 def testNameError(self):
125 def fooNotDeclared():
126 with foo: pass
127 self.assertRaises(NameError, fooNotDeclared)
128
129 def testContextAttributeError(self):
130 class LacksContext(object):
131 def __enter__(self):
132 pass
133
134 def __exit__(self, type, value, traceback):
135 pass
136
137 def fooLacksContext():
138 foo = LacksContext()
139 with foo: pass
140 self.assertRaises(AttributeError, fooLacksContext)
141
142 def testEnterAttributeError(self):
143 class LacksEnter(object):
144 def __context__(self):
145 pass
146
147 def __exit__(self, type, value, traceback):
148 pass
149
150 def fooLacksEnter():
151 foo = LacksEnter()
152 with foo: pass
153 self.assertRaises(AttributeError, fooLacksEnter)
154
155 def testExitAttributeError(self):
156 class LacksExit(object):
157 def __context__(self):
158 pass
159
160 def __enter__(self):
161 pass
162
163 def fooLacksExit():
164 foo = LacksExit()
165 with foo: pass
166 self.assertRaises(AttributeError, fooLacksExit)
167
168 def assertRaisesSyntaxError(self, codestr):
169 def shouldRaiseSyntaxError(s):
170 compile(s, '', 'single')
171 self.assertRaises(SyntaxError, shouldRaiseSyntaxError, codestr)
172
173 def testAssignmentToNoneError(self):
174 self.assertRaisesSyntaxError('with mock as None:\n pass')
175 self.assertRaisesSyntaxError(
176 'with mock as (None):\n'
177 ' pass')
178
179 def testAssignmentToEmptyTupleError(self):
180 self.assertRaisesSyntaxError(
181 'with mock as ():\n'
182 ' pass')
183
184 def testAssignmentToTupleOnlyContainingNoneError(self):
185 self.assertRaisesSyntaxError('with mock as None,:\n pass')
186 self.assertRaisesSyntaxError(
187 'with mock as (None,):\n'
188 ' pass')
189
190 def testAssignmentToTupleContainingNoneError(self):
191 self.assertRaisesSyntaxError(
192 'with mock as (foo, None, bar):\n'
193 ' pass')
194
195 def testContextThrows(self):
196 class ContextThrows(object):
197 def __context__(self):
198 raise RuntimeError("Context threw")
199
200 def shouldThrow():
201 ct = ContextThrows()
202 self.foo = None
203 with ct as self.foo:
204 pass
205 self.assertRaises(RuntimeError, shouldThrow)
206 self.assertEqual(self.foo, None)
207
208 def testEnterThrows(self):
209 class EnterThrows(object):
210 def __context__(self):
211 return self
212
213 def __enter__(self):
214 raise RuntimeError("Context threw")
215
216 def __exit__(self, *args):
217 pass
218
219 def shouldThrow():
220 ct = EnterThrows()
221 self.foo = None
222 with ct as self.foo:
223 pass
224 self.assertRaises(RuntimeError, shouldThrow)
225 self.assertEqual(self.foo, None)
226
227 def testExitThrows(self):
228 class ExitThrows(object):
229 def __context__(self):
230 return self
231 def __enter__(self):
232 return
233 def __exit__(self, *args):
234 raise RuntimeError(42)
235 def shouldThrow():
236 with ExitThrows():
237 pass
238 self.assertRaises(RuntimeError, shouldThrow)
239
240class ContextmanagerAssertionMixin(object):
241 TEST_EXCEPTION = RuntimeError("test exception")
242
243 def assertInWithManagerInvariants(self, mock_manager):
244 self.assertTrue(mock_manager.context_called)
245 self.assertTrue(mock_manager.enter_called)
246 self.assertFalse(mock_manager.exit_called)
247 self.assertEqual(mock_manager.exit_args, None)
248
249 def assertAfterWithManagerInvariants(self, mock_manager, exit_args):
250 self.assertTrue(mock_manager.context_called)
251 self.assertTrue(mock_manager.enter_called)
252 self.assertTrue(mock_manager.exit_called)
253 self.assertEqual(mock_manager.exit_args, exit_args)
254
255 def assertAfterWithManagerInvariantsNoError(self, mock_manager):
256 self.assertAfterWithManagerInvariants(mock_manager,
257 (None, None, None))
258
259 def assertInWithGeneratorInvariants(self, mock_generator):
260 self.assertTrue(mock_generator.yielded)
261 self.assertFalse(mock_generator.stopped)
262
263 def assertAfterWithGeneratorInvariantsNoError(self, mock_generator):
264 self.assertTrue(mock_generator.yielded)
265 self.assertTrue(mock_generator.stopped)
266
267 def raiseTestException(self):
268 raise self.TEST_EXCEPTION
269
270 def assertAfterWithManagerInvariantsWithError(self, mock_manager):
271 self.assertTrue(mock_manager.context_called)
272 self.assertTrue(mock_manager.enter_called)
273 self.assertTrue(mock_manager.exit_called)
274 self.assertEqual(mock_manager.exit_args[0], RuntimeError)
275 self.assertEqual(mock_manager.exit_args[1], self.TEST_EXCEPTION)
276
277 def assertAfterWithGeneratorInvariantsWithError(self, mock_generator):
278 self.assertTrue(mock_generator.yielded)
279 self.assertTrue(mock_generator.stopped)
280
281
282class NonexceptionalTestCase(unittest.TestCase, ContextmanagerAssertionMixin):
283 def testInlineGeneratorSyntax(self):
284 with mock_contextmanager_generator():
285 pass
286
287 def testUnboundGenerator(self):
288 mock = mock_contextmanager_generator()
289 with mock:
290 pass
291 self.assertAfterWithManagerInvariantsNoError(mock)
292
293 def testInlineGeneratorBoundSyntax(self):
294 with mock_contextmanager_generator() as foo:
295 self.assertInWithGeneratorInvariants(foo)
296 # FIXME: In the future, we'll try to keep the bound names from leaking
297 self.assertAfterWithGeneratorInvariantsNoError(foo)
298
299 def testInlineGeneratorBoundToExistingVariable(self):
300 foo = None
301 with mock_contextmanager_generator() as foo:
302 self.assertInWithGeneratorInvariants(foo)
303 self.assertAfterWithGeneratorInvariantsNoError(foo)
304
305 def testInlineGeneratorBoundToDottedVariable(self):
306 with mock_contextmanager_generator() as self.foo:
307 self.assertInWithGeneratorInvariants(self.foo)
308 self.assertAfterWithGeneratorInvariantsNoError(self.foo)
309
310 def testBoundGenerator(self):
311 mock = mock_contextmanager_generator()
312 with mock as foo:
313 self.assertInWithGeneratorInvariants(foo)
314 self.assertInWithManagerInvariants(mock)
315 self.assertAfterWithGeneratorInvariantsNoError(foo)
316 self.assertAfterWithManagerInvariantsNoError(mock)
317
318 def testNestedSingleStatements(self):
319 mock_a = mock_contextmanager_generator()
320 with mock_a as foo:
321 mock_b = mock_contextmanager_generator()
322 with mock_b as bar:
323 self.assertInWithManagerInvariants(mock_a)
324 self.assertInWithManagerInvariants(mock_b)
325 self.assertInWithGeneratorInvariants(foo)
326 self.assertInWithGeneratorInvariants(bar)
327 self.assertAfterWithManagerInvariantsNoError(mock_b)
328 self.assertAfterWithGeneratorInvariantsNoError(bar)
329 self.assertInWithManagerInvariants(mock_a)
330 self.assertInWithGeneratorInvariants(foo)
331 self.assertAfterWithManagerInvariantsNoError(mock_a)
332 self.assertAfterWithGeneratorInvariantsNoError(foo)
333
334
335class NestedNonexceptionalTestCase(unittest.TestCase,
336 ContextmanagerAssertionMixin):
337 def testSingleArgInlineGeneratorSyntax(self):
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000338 with Nested(mock_contextmanager_generator()):
Tim Peters400cbc32006-02-28 18:44:41 +0000339 pass
340
341 def testSingleArgUnbound(self):
342 mock_contextmanager = mock_contextmanager_generator()
343 mock_nested = MockNested(mock_contextmanager)
344 with mock_nested:
345 self.assertInWithManagerInvariants(mock_contextmanager)
346 self.assertInWithManagerInvariants(mock_nested)
347 self.assertAfterWithManagerInvariantsNoError(mock_contextmanager)
348 self.assertAfterWithManagerInvariantsNoError(mock_nested)
349
350 def testSingleArgBoundToNonTuple(self):
351 m = mock_contextmanager_generator()
352 # This will bind all the arguments to nested() into a single list
353 # assigned to foo.
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000354 with Nested(m) as foo:
Tim Peters400cbc32006-02-28 18:44:41 +0000355 self.assertInWithManagerInvariants(m)
356 self.assertAfterWithManagerInvariantsNoError(m)
357
358 def testSingleArgBoundToSingleElementParenthesizedList(self):
359 m = mock_contextmanager_generator()
360 # This will bind all the arguments to nested() into a single list
361 # assigned to foo.
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000362 with Nested(m) as (foo):
Tim Peters400cbc32006-02-28 18:44:41 +0000363 self.assertInWithManagerInvariants(m)
364 self.assertAfterWithManagerInvariantsNoError(m)
365
366 def testSingleArgBoundToMultipleElementTupleError(self):
367 def shouldThrowValueError():
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000368 with Nested(mock_contextmanager_generator()) as (foo, bar):
Tim Peters400cbc32006-02-28 18:44:41 +0000369 pass
370 self.assertRaises(ValueError, shouldThrowValueError)
371
372 def testSingleArgUnbound(self):
373 mock_contextmanager = mock_contextmanager_generator()
374 mock_nested = MockNested(mock_contextmanager)
375 with mock_nested:
376 self.assertInWithManagerInvariants(mock_contextmanager)
377 self.assertInWithManagerInvariants(mock_nested)
378 self.assertAfterWithManagerInvariantsNoError(mock_contextmanager)
379 self.assertAfterWithManagerInvariantsNoError(mock_nested)
380
381 def testMultipleArgUnbound(self):
382 m = mock_contextmanager_generator()
383 n = mock_contextmanager_generator()
384 o = mock_contextmanager_generator()
385 mock_nested = MockNested(m, n, o)
386 with mock_nested:
387 self.assertInWithManagerInvariants(m)
388 self.assertInWithManagerInvariants(n)
389 self.assertInWithManagerInvariants(o)
390 self.assertInWithManagerInvariants(mock_nested)
391 self.assertAfterWithManagerInvariantsNoError(m)
392 self.assertAfterWithManagerInvariantsNoError(n)
393 self.assertAfterWithManagerInvariantsNoError(o)
394 self.assertAfterWithManagerInvariantsNoError(mock_nested)
395
396 def testMultipleArgBound(self):
397 mock_nested = MockNested(mock_contextmanager_generator(),
398 mock_contextmanager_generator(), mock_contextmanager_generator())
399 with mock_nested as (m, n, o):
400 self.assertInWithGeneratorInvariants(m)
401 self.assertInWithGeneratorInvariants(n)
402 self.assertInWithGeneratorInvariants(o)
403 self.assertInWithManagerInvariants(mock_nested)
404 self.assertAfterWithGeneratorInvariantsNoError(m)
405 self.assertAfterWithGeneratorInvariantsNoError(n)
406 self.assertAfterWithGeneratorInvariantsNoError(o)
407 self.assertAfterWithManagerInvariantsNoError(mock_nested)
408
409
410class ExceptionalTestCase(unittest.TestCase, ContextmanagerAssertionMixin):
411 def testSingleResource(self):
412 cm = mock_contextmanager_generator()
413 def shouldThrow():
414 with cm as self.resource:
415 self.assertInWithManagerInvariants(cm)
416 self.assertInWithGeneratorInvariants(self.resource)
417 self.raiseTestException()
418 self.assertRaises(RuntimeError, shouldThrow)
419 self.assertAfterWithManagerInvariantsWithError(cm)
420 self.assertAfterWithGeneratorInvariantsWithError(self.resource)
421
422 def testNestedSingleStatements(self):
423 mock_a = mock_contextmanager_generator()
424 mock_b = mock_contextmanager_generator()
425 def shouldThrow():
426 with mock_a as self.foo:
427 with mock_b as self.bar:
428 self.assertInWithManagerInvariants(mock_a)
429 self.assertInWithManagerInvariants(mock_b)
430 self.assertInWithGeneratorInvariants(self.foo)
431 self.assertInWithGeneratorInvariants(self.bar)
432 self.raiseTestException()
433 self.assertRaises(RuntimeError, shouldThrow)
434 self.assertAfterWithManagerInvariantsWithError(mock_a)
435 self.assertAfterWithManagerInvariantsWithError(mock_b)
436 self.assertAfterWithGeneratorInvariantsWithError(self.foo)
437 self.assertAfterWithGeneratorInvariantsWithError(self.bar)
438
439 def testMultipleResourcesInSingleStatement(self):
440 cm_a = mock_contextmanager_generator()
441 cm_b = mock_contextmanager_generator()
442 mock_nested = MockNested(cm_a, cm_b)
443 def shouldThrow():
444 with mock_nested as (self.resource_a, self.resource_b):
445 self.assertInWithManagerInvariants(cm_a)
446 self.assertInWithManagerInvariants(cm_b)
447 self.assertInWithManagerInvariants(mock_nested)
448 self.assertInWithGeneratorInvariants(self.resource_a)
449 self.assertInWithGeneratorInvariants(self.resource_b)
450 self.raiseTestException()
451 self.assertRaises(RuntimeError, shouldThrow)
452 self.assertAfterWithManagerInvariantsWithError(cm_a)
453 self.assertAfterWithManagerInvariantsWithError(cm_b)
454 self.assertAfterWithManagerInvariantsWithError(mock_nested)
455 self.assertAfterWithGeneratorInvariantsWithError(self.resource_a)
456 self.assertAfterWithGeneratorInvariantsWithError(self.resource_b)
457
458 def testNestedExceptionBeforeInnerStatement(self):
459 mock_a = mock_contextmanager_generator()
460 mock_b = mock_contextmanager_generator()
461 self.bar = None
462 def shouldThrow():
463 with mock_a as self.foo:
464 self.assertInWithManagerInvariants(mock_a)
465 self.assertInWithGeneratorInvariants(self.foo)
466 self.raiseTestException()
467 with mock_b as self.bar:
468 pass
469 self.assertRaises(RuntimeError, shouldThrow)
470 self.assertAfterWithManagerInvariantsWithError(mock_a)
471 self.assertAfterWithGeneratorInvariantsWithError(self.foo)
472
473 # The inner statement stuff should never have been touched
474 self.assertEqual(self.bar, None)
475 self.assertFalse(mock_b.context_called)
476 self.assertFalse(mock_b.enter_called)
477 self.assertFalse(mock_b.exit_called)
478 self.assertEqual(mock_b.exit_args, None)
479
480 def testNestedExceptionAfterInnerStatement(self):
481 mock_a = mock_contextmanager_generator()
482 mock_b = mock_contextmanager_generator()
483 def shouldThrow():
484 with mock_a as self.foo:
485 with mock_b as self.bar:
486 self.assertInWithManagerInvariants(mock_a)
487 self.assertInWithManagerInvariants(mock_b)
488 self.assertInWithGeneratorInvariants(self.foo)
489 self.assertInWithGeneratorInvariants(self.bar)
490 self.raiseTestException()
491 self.assertRaises(RuntimeError, shouldThrow)
492 self.assertAfterWithManagerInvariantsWithError(mock_a)
493 self.assertAfterWithManagerInvariantsNoError(mock_b)
494 self.assertAfterWithGeneratorInvariantsWithError(self.foo)
495 self.assertAfterWithGeneratorInvariantsNoError(self.bar)
496
Phillip J. Eby9444bd52006-04-03 20:05:05 +0000497 def testRaisedStopIteration1(self):
498 @contextmanager
499 def cm():
500 yield
501
502 def shouldThrow():
503 with cm():
504 raise StopIteration("from with")
505
506 self.assertRaises(StopIteration, shouldThrow)
507
508 def testRaisedStopIteration2(self):
509 class cm (object):
510 def __context__(self):
511 return self
512
513 def __enter__(self):
514 pass
515
516 def __exit__(self, type, value, traceback):
517 pass
518
519 def shouldThrow():
520 with cm():
521 raise StopIteration("from with")
522
523 self.assertRaises(StopIteration, shouldThrow)
524
525 def testRaisedGeneratorExit1(self):
526 @contextmanager
527 def cm():
528 yield
529
530 def shouldThrow():
531 with cm():
532 raise GeneratorExit("from with")
533
534 self.assertRaises(GeneratorExit, shouldThrow)
535
536 def testRaisedGeneratorExit2(self):
537 class cm (object):
538 def __context__(self):
539 return self
540
541 def __enter__(self):
542 pass
543
544 def __exit__(self, type, value, traceback):
545 pass
546
547 def shouldThrow():
548 with cm():
549 raise GeneratorExit("from with")
550
551 self.assertRaises(GeneratorExit, shouldThrow)
552
Tim Peters400cbc32006-02-28 18:44:41 +0000553
554class NonLocalFlowControlTestCase(unittest.TestCase):
555
556 def testWithBreak(self):
557 counter = 0
558 while True:
559 counter += 1
560 with mock_contextmanager_generator():
561 counter += 10
562 break
563 counter += 100 # Not reached
564 self.assertEqual(counter, 11)
565
566 def testWithContinue(self):
567 counter = 0
568 while True:
569 counter += 1
570 if counter > 2:
571 break
572 with mock_contextmanager_generator():
573 counter += 10
574 continue
575 counter += 100 # Not reached
576 self.assertEqual(counter, 12)
577
578 def testWithReturn(self):
579 def foo():
580 counter = 0
581 while True:
582 counter += 1
583 with mock_contextmanager_generator():
584 counter += 10
585 return counter
586 counter += 100 # Not reached
587 self.assertEqual(foo(), 11)
588
589 def testWithYield(self):
590 def gen():
591 with mock_contextmanager_generator():
592 yield 12
593 yield 13
594 x = list(gen())
595 self.assertEqual(x, [12, 13])
596
597 def testWithRaise(self):
598 counter = 0
599 try:
600 counter += 1
601 with mock_contextmanager_generator():
602 counter += 10
603 raise RuntimeError
604 counter += 100 # Not reached
605 except RuntimeError:
606 self.assertEqual(counter, 11)
607 else:
608 self.fail("Didn't raise RuntimeError")
609
610
611class AssignmentTargetTestCase(unittest.TestCase):
612
613 def testSingleComplexTarget(self):
614 targets = {1: [0, 1, 2]}
615 with mock_contextmanager_generator() as targets[1][0]:
616 self.assertEqual(targets.keys(), [1])
617 self.assertEqual(targets[1][0].__class__, MockResource)
618 with mock_contextmanager_generator() as targets.values()[0][1]:
619 self.assertEqual(targets.keys(), [1])
620 self.assertEqual(targets[1][1].__class__, MockResource)
621 with mock_contextmanager_generator() as targets[2]:
622 keys = targets.keys()
623 keys.sort()
624 self.assertEqual(keys, [1, 2])
625 class C: pass
626 blah = C()
627 with mock_contextmanager_generator() as blah.foo:
628 self.assertEqual(hasattr(blah, "foo"), True)
629
630 def testMultipleComplexTargets(self):
631 class C:
632 def __context__(self): return self
633 def __enter__(self): return 1, 2, 3
Guido van Rossumf6694362006-03-10 02:28:35 +0000634 def __exit__(self, t, v, tb): pass
Tim Peters400cbc32006-02-28 18:44:41 +0000635 targets = {1: [0, 1, 2]}
636 with C() as (targets[1][0], targets[1][1], targets[1][2]):
637 self.assertEqual(targets, {1: [1, 2, 3]})
638 with C() as (targets.values()[0][2], targets.values()[0][1], targets.values()[0][0]):
639 self.assertEqual(targets, {1: [3, 2, 1]})
640 with C() as (targets[1], targets[2], targets[3]):
641 self.assertEqual(targets, {1: 1, 2: 2, 3: 3})
642 class B: pass
643 blah = B()
644 with C() as (blah.one, blah.two, blah.three):
645 self.assertEqual(blah.one, 1)
646 self.assertEqual(blah.two, 2)
647 self.assertEqual(blah.three, 3)
648
649
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000650class ExitSwallowsExceptionTestCase(unittest.TestCase):
651
Guido van Rossumf6694362006-03-10 02:28:35 +0000652 def testExitTrueSwallowsException(self):
653 class AfricanSwallow:
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000654 def __context__(self): return self
655 def __enter__(self): pass
Guido van Rossumf6694362006-03-10 02:28:35 +0000656 def __exit__(self, t, v, tb): return True
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000657 try:
Guido van Rossumf6694362006-03-10 02:28:35 +0000658 with AfricanSwallow():
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000659 1/0
660 except ZeroDivisionError:
661 self.fail("ZeroDivisionError should have been swallowed")
662
Guido van Rossumf6694362006-03-10 02:28:35 +0000663 def testExitFalseDoesntSwallowException(self):
664 class EuropeanSwallow:
665 def __context__(self): return self
666 def __enter__(self): pass
667 def __exit__(self, t, v, tb): return False
668 try:
669 with EuropeanSwallow():
670 1/0
671 except ZeroDivisionError:
672 pass
673 else:
674 self.fail("ZeroDivisionError should have been raised")
675
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000676
Tim Peters400cbc32006-02-28 18:44:41 +0000677def test_main():
678 run_unittest(FailureTestCase, NonexceptionalTestCase,
679 NestedNonexceptionalTestCase, ExceptionalTestCase,
680 NonLocalFlowControlTestCase,
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000681 AssignmentTargetTestCase,
682 ExitSwallowsExceptionTestCase)
Tim Peters400cbc32006-02-28 18:44:41 +0000683
684
685if __name__ == '__main__':
686 test_main()