blob: 57505085dd3e5a6d4bdab8924b4ea0ffd54e0df7 [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
Nick Coghlanafd5e632006-05-03 13:02:47 +000013from contextlib import GeneratorContextManager, contextmanager
Tim Peters400cbc32006-02-28 18:44:41 +000014from test.test_support import run_unittest
15
16
Nick Coghlanafd5e632006-05-03 13:02:47 +000017class MockContextManager(GeneratorContextManager):
Tim Peters400cbc32006-02-28 18:44:41 +000018 def __init__(self, gen):
Nick Coghlanafd5e632006-05-03 13:02:47 +000019 GeneratorContextManager.__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
Nick Coghlanafd5e632006-05-03 13:02:47 +000026 return GeneratorContextManager.__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)
Nick Coghlanafd5e632006-05-03 13:02:47 +000031 return GeneratorContextManager.__exit__(self, type,
32 value, traceback)
Tim Peters400cbc32006-02-28 18:44:41 +000033
34
35def mock_contextmanager(func):
36 def helper(*args, **kwds):
37 return MockContextManager(func(*args, **kwds))
38 return helper
39
40
41class MockResource(object):
42 def __init__(self):
43 self.yielded = False
44 self.stopped = False
45
46
47@mock_contextmanager
48def mock_contextmanager_generator():
49 mock = MockResource()
50 try:
51 mock.yielded = True
52 yield mock
53 finally:
54 mock.stopped = True
55
56
Guido van Rossum1a5e21e2006-02-28 21:57:43 +000057class Nested(object):
58
Guido van Rossumda5b7012006-05-02 19:47:52 +000059 def __init__(self, *managers):
60 self.managers = managers
Guido van Rossum1a5e21e2006-02-28 21:57:43 +000061 self.entered = None
62
Guido van Rossum1a5e21e2006-02-28 21:57:43 +000063 def __enter__(self):
64 if self.entered is not None:
65 raise RuntimeError("Context is not reentrant")
66 self.entered = deque()
67 vars = []
68 try:
Guido van Rossumda5b7012006-05-02 19:47:52 +000069 for mgr in self.managers:
Guido van Rossum1a5e21e2006-02-28 21:57:43 +000070 vars.append(mgr.__enter__())
71 self.entered.appendleft(mgr)
72 except:
Guido van Rossumf6694362006-03-10 02:28:35 +000073 if not self.__exit__(*sys.exc_info()):
74 raise
Guido van Rossum1a5e21e2006-02-28 21:57:43 +000075 return vars
76
77 def __exit__(self, *exc_info):
78 # Behave like nested with statements
79 # first in, last out
80 # New exceptions override old ones
81 ex = exc_info
82 for mgr in self.entered:
83 try:
Guido van Rossumf6694362006-03-10 02:28:35 +000084 if mgr.__exit__(*ex):
85 ex = (None, None, None)
Guido van Rossum1a5e21e2006-02-28 21:57:43 +000086 except:
87 ex = sys.exc_info()
88 self.entered = None
89 if ex is not exc_info:
90 raise ex[0], ex[1], ex[2]
91
92
93class MockNested(Nested):
Guido van Rossumda5b7012006-05-02 19:47:52 +000094 def __init__(self, *managers):
95 Nested.__init__(self, *managers)
Tim Peters400cbc32006-02-28 18:44:41 +000096 self.enter_called = False
97 self.exit_called = False
98 self.exit_args = None
99
Tim Peters400cbc32006-02-28 18:44:41 +0000100 def __enter__(self):
101 self.enter_called = True
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000102 return Nested.__enter__(self)
Tim Peters400cbc32006-02-28 18:44:41 +0000103
104 def __exit__(self, *exc_info):
105 self.exit_called = True
106 self.exit_args = exc_info
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000107 return Nested.__exit__(self, *exc_info)
Tim Peters400cbc32006-02-28 18:44:41 +0000108
109
110class FailureTestCase(unittest.TestCase):
111 def testNameError(self):
112 def fooNotDeclared():
113 with foo: pass
114 self.assertRaises(NameError, fooNotDeclared)
115
Tim Peters400cbc32006-02-28 18:44:41 +0000116 def testEnterAttributeError(self):
117 class LacksEnter(object):
Tim Peters400cbc32006-02-28 18:44:41 +0000118 def __exit__(self, type, value, traceback):
119 pass
120
121 def fooLacksEnter():
122 foo = LacksEnter()
123 with foo: pass
124 self.assertRaises(AttributeError, fooLacksEnter)
125
126 def testExitAttributeError(self):
127 class LacksExit(object):
Tim Peters400cbc32006-02-28 18:44:41 +0000128 def __enter__(self):
129 pass
130
131 def fooLacksExit():
132 foo = LacksExit()
133 with foo: pass
134 self.assertRaises(AttributeError, fooLacksExit)
135
136 def assertRaisesSyntaxError(self, codestr):
137 def shouldRaiseSyntaxError(s):
138 compile(s, '', 'single')
139 self.assertRaises(SyntaxError, shouldRaiseSyntaxError, codestr)
140
141 def testAssignmentToNoneError(self):
142 self.assertRaisesSyntaxError('with mock as None:\n pass')
143 self.assertRaisesSyntaxError(
144 'with mock as (None):\n'
145 ' pass')
146
147 def testAssignmentToEmptyTupleError(self):
148 self.assertRaisesSyntaxError(
149 'with mock as ():\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
Tim Peters400cbc32006-02-28 18:44:41 +0000163 def testEnterThrows(self):
164 class EnterThrows(object):
Tim Peters400cbc32006-02-28 18:44:41 +0000165 def __enter__(self):
Guido van Rossumda5b7012006-05-02 19:47:52 +0000166 raise RuntimeError("Enter threw")
Tim Peters400cbc32006-02-28 18:44:41 +0000167 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):
Tim Peters400cbc32006-02-28 18:44:41 +0000180 def __enter__(self):
181 return
182 def __exit__(self, *args):
183 raise RuntimeError(42)
184 def shouldThrow():
185 with ExitThrows():
186 pass
187 self.assertRaises(RuntimeError, shouldThrow)
188
189class ContextmanagerAssertionMixin(object):
190 TEST_EXCEPTION = RuntimeError("test exception")
191
192 def assertInWithManagerInvariants(self, mock_manager):
Tim Peters400cbc32006-02-28 18:44:41 +0000193 self.assertTrue(mock_manager.enter_called)
194 self.assertFalse(mock_manager.exit_called)
195 self.assertEqual(mock_manager.exit_args, None)
196
197 def assertAfterWithManagerInvariants(self, mock_manager, exit_args):
Tim Peters400cbc32006-02-28 18:44:41 +0000198 self.assertTrue(mock_manager.enter_called)
199 self.assertTrue(mock_manager.exit_called)
200 self.assertEqual(mock_manager.exit_args, exit_args)
201
202 def assertAfterWithManagerInvariantsNoError(self, mock_manager):
203 self.assertAfterWithManagerInvariants(mock_manager,
204 (None, None, None))
205
206 def assertInWithGeneratorInvariants(self, mock_generator):
207 self.assertTrue(mock_generator.yielded)
208 self.assertFalse(mock_generator.stopped)
209
210 def assertAfterWithGeneratorInvariantsNoError(self, mock_generator):
211 self.assertTrue(mock_generator.yielded)
212 self.assertTrue(mock_generator.stopped)
213
214 def raiseTestException(self):
215 raise self.TEST_EXCEPTION
216
217 def assertAfterWithManagerInvariantsWithError(self, mock_manager):
Tim Peters400cbc32006-02-28 18:44:41 +0000218 self.assertTrue(mock_manager.enter_called)
219 self.assertTrue(mock_manager.exit_called)
220 self.assertEqual(mock_manager.exit_args[0], RuntimeError)
221 self.assertEqual(mock_manager.exit_args[1], self.TEST_EXCEPTION)
222
223 def assertAfterWithGeneratorInvariantsWithError(self, mock_generator):
224 self.assertTrue(mock_generator.yielded)
225 self.assertTrue(mock_generator.stopped)
226
227
228class NonexceptionalTestCase(unittest.TestCase, ContextmanagerAssertionMixin):
229 def testInlineGeneratorSyntax(self):
230 with mock_contextmanager_generator():
231 pass
232
233 def testUnboundGenerator(self):
234 mock = mock_contextmanager_generator()
235 with mock:
236 pass
237 self.assertAfterWithManagerInvariantsNoError(mock)
238
239 def testInlineGeneratorBoundSyntax(self):
240 with mock_contextmanager_generator() as foo:
241 self.assertInWithGeneratorInvariants(foo)
242 # FIXME: In the future, we'll try to keep the bound names from leaking
243 self.assertAfterWithGeneratorInvariantsNoError(foo)
244
245 def testInlineGeneratorBoundToExistingVariable(self):
246 foo = None
247 with mock_contextmanager_generator() as foo:
248 self.assertInWithGeneratorInvariants(foo)
249 self.assertAfterWithGeneratorInvariantsNoError(foo)
250
251 def testInlineGeneratorBoundToDottedVariable(self):
252 with mock_contextmanager_generator() as self.foo:
253 self.assertInWithGeneratorInvariants(self.foo)
254 self.assertAfterWithGeneratorInvariantsNoError(self.foo)
255
256 def testBoundGenerator(self):
257 mock = mock_contextmanager_generator()
258 with mock as foo:
259 self.assertInWithGeneratorInvariants(foo)
260 self.assertInWithManagerInvariants(mock)
261 self.assertAfterWithGeneratorInvariantsNoError(foo)
262 self.assertAfterWithManagerInvariantsNoError(mock)
263
264 def testNestedSingleStatements(self):
265 mock_a = mock_contextmanager_generator()
266 with mock_a as foo:
267 mock_b = mock_contextmanager_generator()
268 with mock_b as bar:
269 self.assertInWithManagerInvariants(mock_a)
270 self.assertInWithManagerInvariants(mock_b)
271 self.assertInWithGeneratorInvariants(foo)
272 self.assertInWithGeneratorInvariants(bar)
273 self.assertAfterWithManagerInvariantsNoError(mock_b)
274 self.assertAfterWithGeneratorInvariantsNoError(bar)
275 self.assertInWithManagerInvariants(mock_a)
276 self.assertInWithGeneratorInvariants(foo)
277 self.assertAfterWithManagerInvariantsNoError(mock_a)
278 self.assertAfterWithGeneratorInvariantsNoError(foo)
279
280
281class NestedNonexceptionalTestCase(unittest.TestCase,
282 ContextmanagerAssertionMixin):
283 def testSingleArgInlineGeneratorSyntax(self):
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000284 with Nested(mock_contextmanager_generator()):
Tim Peters400cbc32006-02-28 18:44:41 +0000285 pass
286
287 def testSingleArgUnbound(self):
288 mock_contextmanager = mock_contextmanager_generator()
289 mock_nested = MockNested(mock_contextmanager)
290 with mock_nested:
291 self.assertInWithManagerInvariants(mock_contextmanager)
292 self.assertInWithManagerInvariants(mock_nested)
293 self.assertAfterWithManagerInvariantsNoError(mock_contextmanager)
294 self.assertAfterWithManagerInvariantsNoError(mock_nested)
295
296 def testSingleArgBoundToNonTuple(self):
297 m = mock_contextmanager_generator()
298 # This will bind all the arguments to nested() into a single list
299 # assigned to foo.
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000300 with Nested(m) as foo:
Tim Peters400cbc32006-02-28 18:44:41 +0000301 self.assertInWithManagerInvariants(m)
302 self.assertAfterWithManagerInvariantsNoError(m)
303
304 def testSingleArgBoundToSingleElementParenthesizedList(self):
305 m = mock_contextmanager_generator()
306 # This will bind all the arguments to nested() into a single list
307 # assigned to foo.
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000308 with Nested(m) as (foo):
Tim Peters400cbc32006-02-28 18:44:41 +0000309 self.assertInWithManagerInvariants(m)
310 self.assertAfterWithManagerInvariantsNoError(m)
311
312 def testSingleArgBoundToMultipleElementTupleError(self):
313 def shouldThrowValueError():
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000314 with Nested(mock_contextmanager_generator()) as (foo, bar):
Tim Peters400cbc32006-02-28 18:44:41 +0000315 pass
316 self.assertRaises(ValueError, shouldThrowValueError)
317
318 def testSingleArgUnbound(self):
319 mock_contextmanager = mock_contextmanager_generator()
320 mock_nested = MockNested(mock_contextmanager)
321 with mock_nested:
322 self.assertInWithManagerInvariants(mock_contextmanager)
323 self.assertInWithManagerInvariants(mock_nested)
324 self.assertAfterWithManagerInvariantsNoError(mock_contextmanager)
325 self.assertAfterWithManagerInvariantsNoError(mock_nested)
326
327 def testMultipleArgUnbound(self):
328 m = mock_contextmanager_generator()
329 n = mock_contextmanager_generator()
330 o = mock_contextmanager_generator()
331 mock_nested = MockNested(m, n, o)
332 with mock_nested:
333 self.assertInWithManagerInvariants(m)
334 self.assertInWithManagerInvariants(n)
335 self.assertInWithManagerInvariants(o)
336 self.assertInWithManagerInvariants(mock_nested)
337 self.assertAfterWithManagerInvariantsNoError(m)
338 self.assertAfterWithManagerInvariantsNoError(n)
339 self.assertAfterWithManagerInvariantsNoError(o)
340 self.assertAfterWithManagerInvariantsNoError(mock_nested)
341
342 def testMultipleArgBound(self):
343 mock_nested = MockNested(mock_contextmanager_generator(),
344 mock_contextmanager_generator(), mock_contextmanager_generator())
345 with mock_nested as (m, n, o):
346 self.assertInWithGeneratorInvariants(m)
347 self.assertInWithGeneratorInvariants(n)
348 self.assertInWithGeneratorInvariants(o)
349 self.assertInWithManagerInvariants(mock_nested)
350 self.assertAfterWithGeneratorInvariantsNoError(m)
351 self.assertAfterWithGeneratorInvariantsNoError(n)
352 self.assertAfterWithGeneratorInvariantsNoError(o)
353 self.assertAfterWithManagerInvariantsNoError(mock_nested)
354
355
356class ExceptionalTestCase(unittest.TestCase, ContextmanagerAssertionMixin):
357 def testSingleResource(self):
358 cm = mock_contextmanager_generator()
359 def shouldThrow():
360 with cm as self.resource:
361 self.assertInWithManagerInvariants(cm)
362 self.assertInWithGeneratorInvariants(self.resource)
363 self.raiseTestException()
364 self.assertRaises(RuntimeError, shouldThrow)
365 self.assertAfterWithManagerInvariantsWithError(cm)
366 self.assertAfterWithGeneratorInvariantsWithError(self.resource)
367
368 def testNestedSingleStatements(self):
369 mock_a = mock_contextmanager_generator()
370 mock_b = mock_contextmanager_generator()
371 def shouldThrow():
372 with mock_a as self.foo:
373 with mock_b as self.bar:
374 self.assertInWithManagerInvariants(mock_a)
375 self.assertInWithManagerInvariants(mock_b)
376 self.assertInWithGeneratorInvariants(self.foo)
377 self.assertInWithGeneratorInvariants(self.bar)
378 self.raiseTestException()
379 self.assertRaises(RuntimeError, shouldThrow)
380 self.assertAfterWithManagerInvariantsWithError(mock_a)
381 self.assertAfterWithManagerInvariantsWithError(mock_b)
382 self.assertAfterWithGeneratorInvariantsWithError(self.foo)
383 self.assertAfterWithGeneratorInvariantsWithError(self.bar)
384
385 def testMultipleResourcesInSingleStatement(self):
386 cm_a = mock_contextmanager_generator()
387 cm_b = mock_contextmanager_generator()
388 mock_nested = MockNested(cm_a, cm_b)
389 def shouldThrow():
390 with mock_nested as (self.resource_a, self.resource_b):
391 self.assertInWithManagerInvariants(cm_a)
392 self.assertInWithManagerInvariants(cm_b)
393 self.assertInWithManagerInvariants(mock_nested)
394 self.assertInWithGeneratorInvariants(self.resource_a)
395 self.assertInWithGeneratorInvariants(self.resource_b)
396 self.raiseTestException()
397 self.assertRaises(RuntimeError, shouldThrow)
398 self.assertAfterWithManagerInvariantsWithError(cm_a)
399 self.assertAfterWithManagerInvariantsWithError(cm_b)
400 self.assertAfterWithManagerInvariantsWithError(mock_nested)
401 self.assertAfterWithGeneratorInvariantsWithError(self.resource_a)
402 self.assertAfterWithGeneratorInvariantsWithError(self.resource_b)
403
404 def testNestedExceptionBeforeInnerStatement(self):
405 mock_a = mock_contextmanager_generator()
406 mock_b = mock_contextmanager_generator()
407 self.bar = None
408 def shouldThrow():
409 with mock_a as self.foo:
410 self.assertInWithManagerInvariants(mock_a)
411 self.assertInWithGeneratorInvariants(self.foo)
412 self.raiseTestException()
413 with mock_b as self.bar:
414 pass
415 self.assertRaises(RuntimeError, shouldThrow)
416 self.assertAfterWithManagerInvariantsWithError(mock_a)
417 self.assertAfterWithGeneratorInvariantsWithError(self.foo)
418
419 # The inner statement stuff should never have been touched
420 self.assertEqual(self.bar, None)
Tim Peters400cbc32006-02-28 18:44:41 +0000421 self.assertFalse(mock_b.enter_called)
422 self.assertFalse(mock_b.exit_called)
423 self.assertEqual(mock_b.exit_args, None)
424
425 def testNestedExceptionAfterInnerStatement(self):
426 mock_a = mock_contextmanager_generator()
427 mock_b = mock_contextmanager_generator()
428 def shouldThrow():
429 with mock_a as self.foo:
430 with mock_b as self.bar:
431 self.assertInWithManagerInvariants(mock_a)
432 self.assertInWithManagerInvariants(mock_b)
433 self.assertInWithGeneratorInvariants(self.foo)
434 self.assertInWithGeneratorInvariants(self.bar)
435 self.raiseTestException()
436 self.assertRaises(RuntimeError, shouldThrow)
437 self.assertAfterWithManagerInvariantsWithError(mock_a)
438 self.assertAfterWithManagerInvariantsNoError(mock_b)
439 self.assertAfterWithGeneratorInvariantsWithError(self.foo)
440 self.assertAfterWithGeneratorInvariantsNoError(self.bar)
441
Phillip J. Eby9444bd52006-04-03 20:05:05 +0000442 def testRaisedStopIteration1(self):
Nick Coghlanafd5e632006-05-03 13:02:47 +0000443 @contextmanager
Phillip J. Eby9444bd52006-04-03 20:05:05 +0000444 def cm():
445 yield
446
447 def shouldThrow():
448 with cm():
449 raise StopIteration("from with")
450
451 self.assertRaises(StopIteration, shouldThrow)
452
453 def testRaisedStopIteration2(self):
Guido van Rossumda5b7012006-05-02 19:47:52 +0000454 class cm(object):
Phillip J. Eby9444bd52006-04-03 20:05:05 +0000455 def __enter__(self):
456 pass
Phillip J. Eby9444bd52006-04-03 20:05:05 +0000457 def __exit__(self, type, value, traceback):
458 pass
459
460 def shouldThrow():
461 with cm():
462 raise StopIteration("from with")
463
464 self.assertRaises(StopIteration, shouldThrow)
465
466 def testRaisedGeneratorExit1(self):
Nick Coghlanafd5e632006-05-03 13:02:47 +0000467 @contextmanager
Phillip J. Eby9444bd52006-04-03 20:05:05 +0000468 def cm():
469 yield
470
471 def shouldThrow():
472 with cm():
473 raise GeneratorExit("from with")
474
475 self.assertRaises(GeneratorExit, shouldThrow)
476
477 def testRaisedGeneratorExit2(self):
478 class cm (object):
Phillip J. Eby9444bd52006-04-03 20:05:05 +0000479 def __enter__(self):
480 pass
Phillip J. Eby9444bd52006-04-03 20:05:05 +0000481 def __exit__(self, type, value, traceback):
482 pass
483
484 def shouldThrow():
485 with cm():
486 raise GeneratorExit("from with")
487
488 self.assertRaises(GeneratorExit, shouldThrow)
489
Tim Peters400cbc32006-02-28 18:44:41 +0000490
491class NonLocalFlowControlTestCase(unittest.TestCase):
492
493 def testWithBreak(self):
494 counter = 0
495 while True:
496 counter += 1
497 with mock_contextmanager_generator():
498 counter += 10
499 break
500 counter += 100 # Not reached
501 self.assertEqual(counter, 11)
502
503 def testWithContinue(self):
504 counter = 0
505 while True:
506 counter += 1
507 if counter > 2:
508 break
509 with mock_contextmanager_generator():
510 counter += 10
511 continue
512 counter += 100 # Not reached
513 self.assertEqual(counter, 12)
514
515 def testWithReturn(self):
516 def foo():
517 counter = 0
518 while True:
519 counter += 1
520 with mock_contextmanager_generator():
521 counter += 10
522 return counter
523 counter += 100 # Not reached
524 self.assertEqual(foo(), 11)
525
526 def testWithYield(self):
527 def gen():
528 with mock_contextmanager_generator():
529 yield 12
530 yield 13
531 x = list(gen())
532 self.assertEqual(x, [12, 13])
533
534 def testWithRaise(self):
535 counter = 0
536 try:
537 counter += 1
538 with mock_contextmanager_generator():
539 counter += 10
540 raise RuntimeError
541 counter += 100 # Not reached
542 except RuntimeError:
543 self.assertEqual(counter, 11)
544 else:
545 self.fail("Didn't raise RuntimeError")
546
547
548class AssignmentTargetTestCase(unittest.TestCase):
549
550 def testSingleComplexTarget(self):
551 targets = {1: [0, 1, 2]}
552 with mock_contextmanager_generator() as targets[1][0]:
553 self.assertEqual(targets.keys(), [1])
554 self.assertEqual(targets[1][0].__class__, MockResource)
555 with mock_contextmanager_generator() as targets.values()[0][1]:
556 self.assertEqual(targets.keys(), [1])
557 self.assertEqual(targets[1][1].__class__, MockResource)
558 with mock_contextmanager_generator() as targets[2]:
559 keys = targets.keys()
560 keys.sort()
561 self.assertEqual(keys, [1, 2])
562 class C: pass
563 blah = C()
564 with mock_contextmanager_generator() as blah.foo:
565 self.assertEqual(hasattr(blah, "foo"), True)
566
567 def testMultipleComplexTargets(self):
568 class C:
Tim Peters400cbc32006-02-28 18:44:41 +0000569 def __enter__(self): return 1, 2, 3
Guido van Rossumf6694362006-03-10 02:28:35 +0000570 def __exit__(self, t, v, tb): pass
Tim Peters400cbc32006-02-28 18:44:41 +0000571 targets = {1: [0, 1, 2]}
572 with C() as (targets[1][0], targets[1][1], targets[1][2]):
573 self.assertEqual(targets, {1: [1, 2, 3]})
574 with C() as (targets.values()[0][2], targets.values()[0][1], targets.values()[0][0]):
575 self.assertEqual(targets, {1: [3, 2, 1]})
576 with C() as (targets[1], targets[2], targets[3]):
577 self.assertEqual(targets, {1: 1, 2: 2, 3: 3})
578 class B: pass
579 blah = B()
580 with C() as (blah.one, blah.two, blah.three):
581 self.assertEqual(blah.one, 1)
582 self.assertEqual(blah.two, 2)
583 self.assertEqual(blah.three, 3)
584
585
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000586class ExitSwallowsExceptionTestCase(unittest.TestCase):
587
Guido van Rossumf6694362006-03-10 02:28:35 +0000588 def testExitTrueSwallowsException(self):
589 class AfricanSwallow:
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000590 def __enter__(self): pass
Guido van Rossumf6694362006-03-10 02:28:35 +0000591 def __exit__(self, t, v, tb): return True
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000592 try:
Guido van Rossumf6694362006-03-10 02:28:35 +0000593 with AfricanSwallow():
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000594 1/0
595 except ZeroDivisionError:
596 self.fail("ZeroDivisionError should have been swallowed")
597
Guido van Rossumf6694362006-03-10 02:28:35 +0000598 def testExitFalseDoesntSwallowException(self):
599 class EuropeanSwallow:
Guido van Rossumf6694362006-03-10 02:28:35 +0000600 def __enter__(self): pass
601 def __exit__(self, t, v, tb): return False
602 try:
603 with EuropeanSwallow():
604 1/0
605 except ZeroDivisionError:
606 pass
607 else:
608 self.fail("ZeroDivisionError should have been raised")
609
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000610
Tim Peters400cbc32006-02-28 18:44:41 +0000611def test_main():
612 run_unittest(FailureTestCase, NonexceptionalTestCase,
613 NestedNonexceptionalTestCase, ExceptionalTestCase,
614 NonLocalFlowControlTestCase,
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000615 AssignmentTargetTestCase,
616 ExitSwallowsExceptionTestCase)
Tim Peters400cbc32006-02-28 18:44:41 +0000617
618
619if __name__ == '__main__':
620 test_main()