blob: 765bfec397933a335e551779caeef7a2e5b64736 [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
Tim Petersd845e532006-04-26 01:15:53 +000013from contextlib import GeneratorContext, contextfactory
Tim Peters400cbc32006-02-28 18:44:41 +000014from test.test_support import run_unittest
15
16
Tim Petersd845e532006-04-26 01:15:53 +000017class MockContextManager(GeneratorContext):
Tim Peters400cbc32006-02-28 18:44:41 +000018 def __init__(self, gen):
Tim Petersd845e532006-04-26 01:15:53 +000019 GeneratorContext.__init__(self, gen)
Tim Peters400cbc32006-02-28 18:44:41 +000020 self.enter_called = False
21 self.exit_called = False
22 self.exit_args = None
23
Tim Peters400cbc32006-02-28 18:44:41 +000024 def __enter__(self):
25 self.enter_called = True
Tim Petersd845e532006-04-26 01:15:53 +000026 return GeneratorContext.__enter__(self)
Tim Peters400cbc32006-02-28 18:44:41 +000027
28 def __exit__(self, type, value, traceback):
29 self.exit_called = True
30 self.exit_args = (type, value, traceback)
Tim Petersd845e532006-04-26 01:15:53 +000031 return GeneratorContext.__exit__(self, type, value, traceback)
Tim Peters400cbc32006-02-28 18:44:41 +000032
33
34def mock_contextmanager(func):
35 def helper(*args, **kwds):
36 return MockContextManager(func(*args, **kwds))
37 return helper
38
39
40class MockResource(object):
41 def __init__(self):
42 self.yielded = False
43 self.stopped = False
44
45
46@mock_contextmanager
47def mock_contextmanager_generator():
48 mock = MockResource()
49 try:
50 mock.yielded = True
51 yield mock
52 finally:
53 mock.stopped = True
54
55
Guido van Rossum1a5e21e2006-02-28 21:57:43 +000056class Nested(object):
57
Guido van Rossumda5b7012006-05-02 19:47:52 +000058 def __init__(self, *managers):
59 self.managers = managers
Guido van Rossum1a5e21e2006-02-28 21:57:43 +000060 self.entered = None
61
Guido van Rossum1a5e21e2006-02-28 21:57:43 +000062 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:
Guido van Rossumda5b7012006-05-02 19:47:52 +000068 for mgr in self.managers:
Guido van Rossum1a5e21e2006-02-28 21:57:43 +000069 vars.append(mgr.__enter__())
70 self.entered.appendleft(mgr)
71 except:
Guido van Rossumf6694362006-03-10 02:28:35 +000072 if not self.__exit__(*sys.exc_info()):
73 raise
Guido van Rossum1a5e21e2006-02-28 21:57:43 +000074 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:
Guido van Rossumf6694362006-03-10 02:28:35 +000083 if mgr.__exit__(*ex):
84 ex = (None, None, None)
Guido van Rossum1a5e21e2006-02-28 21:57:43 +000085 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
92class MockNested(Nested):
Guido van Rossumda5b7012006-05-02 19:47:52 +000093 def __init__(self, *managers):
94 Nested.__init__(self, *managers)
Tim Peters400cbc32006-02-28 18:44:41 +000095 self.enter_called = False
96 self.exit_called = False
97 self.exit_args = None
98
Tim Peters400cbc32006-02-28 18:44:41 +000099 def __enter__(self):
100 self.enter_called = True
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000101 return Nested.__enter__(self)
Tim Peters400cbc32006-02-28 18:44:41 +0000102
103 def __exit__(self, *exc_info):
104 self.exit_called = True
105 self.exit_args = exc_info
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000106 return Nested.__exit__(self, *exc_info)
Tim Peters400cbc32006-02-28 18:44:41 +0000107
108
109class FailureTestCase(unittest.TestCase):
110 def testNameError(self):
111 def fooNotDeclared():
112 with foo: pass
113 self.assertRaises(NameError, fooNotDeclared)
114
Tim Peters400cbc32006-02-28 18:44:41 +0000115 def testEnterAttributeError(self):
116 class LacksEnter(object):
Tim Peters400cbc32006-02-28 18:44:41 +0000117 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):
Tim Peters400cbc32006-02-28 18:44:41 +0000127 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
Tim Peters400cbc32006-02-28 18:44:41 +0000162 def testEnterThrows(self):
163 class EnterThrows(object):
Tim Peters400cbc32006-02-28 18:44:41 +0000164 def __enter__(self):
Guido van Rossumda5b7012006-05-02 19:47:52 +0000165 raise RuntimeError("Enter threw")
Tim Peters400cbc32006-02-28 18:44:41 +0000166 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):
Tim Peters400cbc32006-02-28 18:44:41 +0000179 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
188class ContextmanagerAssertionMixin(object):
189 TEST_EXCEPTION = RuntimeError("test exception")
190
191 def assertInWithManagerInvariants(self, mock_manager):
Tim Peters400cbc32006-02-28 18:44:41 +0000192 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):
Tim Peters400cbc32006-02-28 18:44:41 +0000197 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):
Tim Peters400cbc32006-02-28 18:44:41 +0000217 self.assertTrue(mock_manager.enter_called)
218 self.assertTrue(mock_manager.exit_called)
219 self.assertEqual(mock_manager.exit_args[0], RuntimeError)
220 self.assertEqual(mock_manager.exit_args[1], self.TEST_EXCEPTION)
221
222 def assertAfterWithGeneratorInvariantsWithError(self, mock_generator):
223 self.assertTrue(mock_generator.yielded)
224 self.assertTrue(mock_generator.stopped)
225
226
227class NonexceptionalTestCase(unittest.TestCase, ContextmanagerAssertionMixin):
228 def testInlineGeneratorSyntax(self):
229 with mock_contextmanager_generator():
230 pass
231
232 def testUnboundGenerator(self):
233 mock = mock_contextmanager_generator()
234 with mock:
235 pass
236 self.assertAfterWithManagerInvariantsNoError(mock)
237
238 def testInlineGeneratorBoundSyntax(self):
239 with mock_contextmanager_generator() as foo:
240 self.assertInWithGeneratorInvariants(foo)
241 # FIXME: In the future, we'll try to keep the bound names from leaking
242 self.assertAfterWithGeneratorInvariantsNoError(foo)
243
244 def testInlineGeneratorBoundToExistingVariable(self):
245 foo = None
246 with mock_contextmanager_generator() as foo:
247 self.assertInWithGeneratorInvariants(foo)
248 self.assertAfterWithGeneratorInvariantsNoError(foo)
249
250 def testInlineGeneratorBoundToDottedVariable(self):
251 with mock_contextmanager_generator() as self.foo:
252 self.assertInWithGeneratorInvariants(self.foo)
253 self.assertAfterWithGeneratorInvariantsNoError(self.foo)
254
255 def testBoundGenerator(self):
256 mock = mock_contextmanager_generator()
257 with mock as foo:
258 self.assertInWithGeneratorInvariants(foo)
259 self.assertInWithManagerInvariants(mock)
260 self.assertAfterWithGeneratorInvariantsNoError(foo)
261 self.assertAfterWithManagerInvariantsNoError(mock)
262
263 def testNestedSingleStatements(self):
264 mock_a = mock_contextmanager_generator()
265 with mock_a as foo:
266 mock_b = mock_contextmanager_generator()
267 with mock_b as bar:
268 self.assertInWithManagerInvariants(mock_a)
269 self.assertInWithManagerInvariants(mock_b)
270 self.assertInWithGeneratorInvariants(foo)
271 self.assertInWithGeneratorInvariants(bar)
272 self.assertAfterWithManagerInvariantsNoError(mock_b)
273 self.assertAfterWithGeneratorInvariantsNoError(bar)
274 self.assertInWithManagerInvariants(mock_a)
275 self.assertInWithGeneratorInvariants(foo)
276 self.assertAfterWithManagerInvariantsNoError(mock_a)
277 self.assertAfterWithGeneratorInvariantsNoError(foo)
278
279
280class NestedNonexceptionalTestCase(unittest.TestCase,
281 ContextmanagerAssertionMixin):
282 def testSingleArgInlineGeneratorSyntax(self):
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000283 with Nested(mock_contextmanager_generator()):
Tim Peters400cbc32006-02-28 18:44:41 +0000284 pass
285
286 def testSingleArgUnbound(self):
287 mock_contextmanager = mock_contextmanager_generator()
288 mock_nested = MockNested(mock_contextmanager)
289 with mock_nested:
290 self.assertInWithManagerInvariants(mock_contextmanager)
291 self.assertInWithManagerInvariants(mock_nested)
292 self.assertAfterWithManagerInvariantsNoError(mock_contextmanager)
293 self.assertAfterWithManagerInvariantsNoError(mock_nested)
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.
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000299 with Nested(m) as foo:
Tim Peters400cbc32006-02-28 18:44:41 +0000300 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.
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000307 with Nested(m) as (foo):
Tim Peters400cbc32006-02-28 18:44:41 +0000308 self.assertInWithManagerInvariants(m)
309 self.assertAfterWithManagerInvariantsNoError(m)
310
311 def testSingleArgBoundToMultipleElementTupleError(self):
312 def shouldThrowValueError():
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000313 with Nested(mock_contextmanager_generator()) as (foo, bar):
Tim Peters400cbc32006-02-28 18:44:41 +0000314 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(unittest.TestCase, ContextmanagerAssertionMixin):
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 testNestedSingleStatements(self):
368 mock_a = mock_contextmanager_generator()
369 mock_b = mock_contextmanager_generator()
370 def shouldThrow():
371 with mock_a as self.foo:
372 with mock_b as self.bar:
373 self.assertInWithManagerInvariants(mock_a)
374 self.assertInWithManagerInvariants(mock_b)
375 self.assertInWithGeneratorInvariants(self.foo)
376 self.assertInWithGeneratorInvariants(self.bar)
377 self.raiseTestException()
378 self.assertRaises(RuntimeError, shouldThrow)
379 self.assertAfterWithManagerInvariantsWithError(mock_a)
380 self.assertAfterWithManagerInvariantsWithError(mock_b)
381 self.assertAfterWithGeneratorInvariantsWithError(self.foo)
382 self.assertAfterWithGeneratorInvariantsWithError(self.bar)
383
384 def testMultipleResourcesInSingleStatement(self):
385 cm_a = mock_contextmanager_generator()
386 cm_b = mock_contextmanager_generator()
387 mock_nested = MockNested(cm_a, cm_b)
388 def shouldThrow():
389 with mock_nested as (self.resource_a, self.resource_b):
390 self.assertInWithManagerInvariants(cm_a)
391 self.assertInWithManagerInvariants(cm_b)
392 self.assertInWithManagerInvariants(mock_nested)
393 self.assertInWithGeneratorInvariants(self.resource_a)
394 self.assertInWithGeneratorInvariants(self.resource_b)
395 self.raiseTestException()
396 self.assertRaises(RuntimeError, shouldThrow)
397 self.assertAfterWithManagerInvariantsWithError(cm_a)
398 self.assertAfterWithManagerInvariantsWithError(cm_b)
399 self.assertAfterWithManagerInvariantsWithError(mock_nested)
400 self.assertAfterWithGeneratorInvariantsWithError(self.resource_a)
401 self.assertAfterWithGeneratorInvariantsWithError(self.resource_b)
402
403 def testNestedExceptionBeforeInnerStatement(self):
404 mock_a = mock_contextmanager_generator()
405 mock_b = mock_contextmanager_generator()
406 self.bar = None
407 def shouldThrow():
408 with mock_a as self.foo:
409 self.assertInWithManagerInvariants(mock_a)
410 self.assertInWithGeneratorInvariants(self.foo)
411 self.raiseTestException()
412 with mock_b as self.bar:
413 pass
414 self.assertRaises(RuntimeError, shouldThrow)
415 self.assertAfterWithManagerInvariantsWithError(mock_a)
416 self.assertAfterWithGeneratorInvariantsWithError(self.foo)
417
418 # The inner statement stuff should never have been touched
419 self.assertEqual(self.bar, None)
Tim Peters400cbc32006-02-28 18:44:41 +0000420 self.assertFalse(mock_b.enter_called)
421 self.assertFalse(mock_b.exit_called)
422 self.assertEqual(mock_b.exit_args, None)
423
424 def testNestedExceptionAfterInnerStatement(self):
425 mock_a = mock_contextmanager_generator()
426 mock_b = mock_contextmanager_generator()
427 def shouldThrow():
428 with mock_a as self.foo:
429 with mock_b as self.bar:
430 self.assertInWithManagerInvariants(mock_a)
431 self.assertInWithManagerInvariants(mock_b)
432 self.assertInWithGeneratorInvariants(self.foo)
433 self.assertInWithGeneratorInvariants(self.bar)
434 self.raiseTestException()
435 self.assertRaises(RuntimeError, shouldThrow)
436 self.assertAfterWithManagerInvariantsWithError(mock_a)
437 self.assertAfterWithManagerInvariantsNoError(mock_b)
438 self.assertAfterWithGeneratorInvariantsWithError(self.foo)
439 self.assertAfterWithGeneratorInvariantsNoError(self.bar)
440
Phillip J. Eby9444bd52006-04-03 20:05:05 +0000441 def testRaisedStopIteration1(self):
Tim Petersd845e532006-04-26 01:15:53 +0000442 @contextfactory
Phillip J. Eby9444bd52006-04-03 20:05:05 +0000443 def cm():
444 yield
445
446 def shouldThrow():
447 with cm():
448 raise StopIteration("from with")
449
450 self.assertRaises(StopIteration, shouldThrow)
451
452 def testRaisedStopIteration2(self):
Guido van Rossumda5b7012006-05-02 19:47:52 +0000453 class cm(object):
Phillip J. Eby9444bd52006-04-03 20:05:05 +0000454 def __enter__(self):
455 pass
Phillip J. Eby9444bd52006-04-03 20:05:05 +0000456 def __exit__(self, type, value, traceback):
457 pass
458
459 def shouldThrow():
460 with cm():
461 raise StopIteration("from with")
462
463 self.assertRaises(StopIteration, shouldThrow)
464
465 def testRaisedGeneratorExit1(self):
Tim Petersd845e532006-04-26 01:15:53 +0000466 @contextfactory
Phillip J. Eby9444bd52006-04-03 20:05:05 +0000467 def cm():
468 yield
469
470 def shouldThrow():
471 with cm():
472 raise GeneratorExit("from with")
473
474 self.assertRaises(GeneratorExit, shouldThrow)
475
476 def testRaisedGeneratorExit2(self):
477 class cm (object):
Phillip J. Eby9444bd52006-04-03 20:05:05 +0000478 def __enter__(self):
479 pass
Phillip J. Eby9444bd52006-04-03 20:05:05 +0000480 def __exit__(self, type, value, traceback):
481 pass
482
483 def shouldThrow():
484 with cm():
485 raise GeneratorExit("from with")
486
487 self.assertRaises(GeneratorExit, shouldThrow)
488
Tim Peters400cbc32006-02-28 18:44:41 +0000489
490class NonLocalFlowControlTestCase(unittest.TestCase):
491
492 def testWithBreak(self):
493 counter = 0
494 while True:
495 counter += 1
496 with mock_contextmanager_generator():
497 counter += 10
498 break
499 counter += 100 # Not reached
500 self.assertEqual(counter, 11)
501
502 def testWithContinue(self):
503 counter = 0
504 while True:
505 counter += 1
506 if counter > 2:
507 break
508 with mock_contextmanager_generator():
509 counter += 10
510 continue
511 counter += 100 # Not reached
512 self.assertEqual(counter, 12)
513
514 def testWithReturn(self):
515 def foo():
516 counter = 0
517 while True:
518 counter += 1
519 with mock_contextmanager_generator():
520 counter += 10
521 return counter
522 counter += 100 # Not reached
523 self.assertEqual(foo(), 11)
524
525 def testWithYield(self):
526 def gen():
527 with mock_contextmanager_generator():
528 yield 12
529 yield 13
530 x = list(gen())
531 self.assertEqual(x, [12, 13])
532
533 def testWithRaise(self):
534 counter = 0
535 try:
536 counter += 1
537 with mock_contextmanager_generator():
538 counter += 10
539 raise RuntimeError
540 counter += 100 # Not reached
541 except RuntimeError:
542 self.assertEqual(counter, 11)
543 else:
544 self.fail("Didn't raise RuntimeError")
545
546
547class AssignmentTargetTestCase(unittest.TestCase):
548
549 def testSingleComplexTarget(self):
550 targets = {1: [0, 1, 2]}
551 with mock_contextmanager_generator() as targets[1][0]:
552 self.assertEqual(targets.keys(), [1])
553 self.assertEqual(targets[1][0].__class__, MockResource)
554 with mock_contextmanager_generator() as targets.values()[0][1]:
555 self.assertEqual(targets.keys(), [1])
556 self.assertEqual(targets[1][1].__class__, MockResource)
557 with mock_contextmanager_generator() as targets[2]:
558 keys = targets.keys()
559 keys.sort()
560 self.assertEqual(keys, [1, 2])
561 class C: pass
562 blah = C()
563 with mock_contextmanager_generator() as blah.foo:
564 self.assertEqual(hasattr(blah, "foo"), True)
565
566 def testMultipleComplexTargets(self):
567 class C:
Tim Peters400cbc32006-02-28 18:44:41 +0000568 def __enter__(self): return 1, 2, 3
Guido van Rossumf6694362006-03-10 02:28:35 +0000569 def __exit__(self, t, v, tb): pass
Tim Peters400cbc32006-02-28 18:44:41 +0000570 targets = {1: [0, 1, 2]}
571 with C() as (targets[1][0], targets[1][1], targets[1][2]):
572 self.assertEqual(targets, {1: [1, 2, 3]})
573 with C() as (targets.values()[0][2], targets.values()[0][1], targets.values()[0][0]):
574 self.assertEqual(targets, {1: [3, 2, 1]})
575 with C() as (targets[1], targets[2], targets[3]):
576 self.assertEqual(targets, {1: 1, 2: 2, 3: 3})
577 class B: pass
578 blah = B()
579 with C() as (blah.one, blah.two, blah.three):
580 self.assertEqual(blah.one, 1)
581 self.assertEqual(blah.two, 2)
582 self.assertEqual(blah.three, 3)
583
584
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000585class ExitSwallowsExceptionTestCase(unittest.TestCase):
586
Guido van Rossumf6694362006-03-10 02:28:35 +0000587 def testExitTrueSwallowsException(self):
588 class AfricanSwallow:
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000589 def __enter__(self): pass
Guido van Rossumf6694362006-03-10 02:28:35 +0000590 def __exit__(self, t, v, tb): return True
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000591 try:
Guido van Rossumf6694362006-03-10 02:28:35 +0000592 with AfricanSwallow():
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000593 1/0
594 except ZeroDivisionError:
595 self.fail("ZeroDivisionError should have been swallowed")
596
Guido van Rossumf6694362006-03-10 02:28:35 +0000597 def testExitFalseDoesntSwallowException(self):
598 class EuropeanSwallow:
Guido van Rossumf6694362006-03-10 02:28:35 +0000599 def __enter__(self): pass
600 def __exit__(self, t, v, tb): return False
601 try:
602 with EuropeanSwallow():
603 1/0
604 except ZeroDivisionError:
605 pass
606 else:
607 self.fail("ZeroDivisionError should have been raised")
608
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000609
Tim Peters400cbc32006-02-28 18:44:41 +0000610def test_main():
611 run_unittest(FailureTestCase, NonexceptionalTestCase,
612 NestedNonexceptionalTestCase, ExceptionalTestCase,
613 NonLocalFlowControlTestCase,
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000614 AssignmentTargetTestCase,
615 ExitSwallowsExceptionTestCase)
Tim Peters400cbc32006-02-28 18:44:41 +0000616
617
618if __name__ == '__main__':
619 test_main()