blob: e77846399d7e76cb7956a06c62bac36ac3c83964 [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)
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
26 return GeneratorContextManager.__enter__(self)
27
28 def __exit__(self, type, value, traceback):
29 self.exit_called = True
30 self.exit_args = (type, value, traceback)
Thomas Wouters477c8d52006-05-27 19:21: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
Thomas Wouters477c8d52006-05-27 19:21:47 +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:
Thomas Wouters477c8d52006-05-27 19:21:47 +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:
Collin Winter828f04a2007-08-31 00:04:24 +000090 raise ex[0](ex[1]).with_traceback(ex[2])
Guido van Rossum1a5e21e2006-02-28 21:57:43 +000091
92
93class MockNested(Nested):
Thomas Wouters477c8d52006-05-27 19:21:47 +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):
Thomas Wouters477c8d52006-05-27 19:21:47 +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):
Collin Winterba21f612007-09-01 20:29:04 +0000190
191 def setUp(self):
192 self.TEST_EXCEPTION = RuntimeError("test exception")
Tim Peters400cbc32006-02-28 18:44:41 +0000193
194 def assertInWithManagerInvariants(self, mock_manager):
Tim Peters400cbc32006-02-28 18:44:41 +0000195 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):
Tim Peters400cbc32006-02-28 18:44:41 +0000200 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):
Tim Peters400cbc32006-02-28 18:44:41 +0000220 self.assertTrue(mock_manager.enter_called)
221 self.assertTrue(mock_manager.exit_called)
222 self.assertEqual(mock_manager.exit_args[0], RuntimeError)
223 self.assertEqual(mock_manager.exit_args[1], self.TEST_EXCEPTION)
224
225 def assertAfterWithGeneratorInvariantsWithError(self, mock_generator):
226 self.assertTrue(mock_generator.yielded)
227 self.assertTrue(mock_generator.stopped)
228
229
230class NonexceptionalTestCase(unittest.TestCase, ContextmanagerAssertionMixin):
231 def testInlineGeneratorSyntax(self):
232 with mock_contextmanager_generator():
233 pass
234
235 def testUnboundGenerator(self):
236 mock = mock_contextmanager_generator()
237 with mock:
238 pass
239 self.assertAfterWithManagerInvariantsNoError(mock)
240
241 def testInlineGeneratorBoundSyntax(self):
242 with mock_contextmanager_generator() as foo:
243 self.assertInWithGeneratorInvariants(foo)
244 # FIXME: In the future, we'll try to keep the bound names from leaking
245 self.assertAfterWithGeneratorInvariantsNoError(foo)
246
247 def testInlineGeneratorBoundToExistingVariable(self):
248 foo = None
249 with mock_contextmanager_generator() as foo:
250 self.assertInWithGeneratorInvariants(foo)
251 self.assertAfterWithGeneratorInvariantsNoError(foo)
252
253 def testInlineGeneratorBoundToDottedVariable(self):
254 with mock_contextmanager_generator() as self.foo:
255 self.assertInWithGeneratorInvariants(self.foo)
256 self.assertAfterWithGeneratorInvariantsNoError(self.foo)
257
258 def testBoundGenerator(self):
259 mock = mock_contextmanager_generator()
260 with mock as foo:
261 self.assertInWithGeneratorInvariants(foo)
262 self.assertInWithManagerInvariants(mock)
263 self.assertAfterWithGeneratorInvariantsNoError(foo)
264 self.assertAfterWithManagerInvariantsNoError(mock)
265
266 def testNestedSingleStatements(self):
267 mock_a = mock_contextmanager_generator()
268 with mock_a as foo:
269 mock_b = mock_contextmanager_generator()
270 with mock_b as bar:
271 self.assertInWithManagerInvariants(mock_a)
272 self.assertInWithManagerInvariants(mock_b)
273 self.assertInWithGeneratorInvariants(foo)
274 self.assertInWithGeneratorInvariants(bar)
275 self.assertAfterWithManagerInvariantsNoError(mock_b)
276 self.assertAfterWithGeneratorInvariantsNoError(bar)
277 self.assertInWithManagerInvariants(mock_a)
278 self.assertInWithGeneratorInvariants(foo)
279 self.assertAfterWithManagerInvariantsNoError(mock_a)
280 self.assertAfterWithGeneratorInvariantsNoError(foo)
281
282
283class NestedNonexceptionalTestCase(unittest.TestCase,
284 ContextmanagerAssertionMixin):
285 def testSingleArgInlineGeneratorSyntax(self):
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000286 with Nested(mock_contextmanager_generator()):
Tim Peters400cbc32006-02-28 18:44:41 +0000287 pass
288
289 def testSingleArgUnbound(self):
290 mock_contextmanager = mock_contextmanager_generator()
291 mock_nested = MockNested(mock_contextmanager)
292 with mock_nested:
293 self.assertInWithManagerInvariants(mock_contextmanager)
294 self.assertInWithManagerInvariants(mock_nested)
295 self.assertAfterWithManagerInvariantsNoError(mock_contextmanager)
296 self.assertAfterWithManagerInvariantsNoError(mock_nested)
297
298 def testSingleArgBoundToNonTuple(self):
299 m = mock_contextmanager_generator()
300 # This will bind all the arguments to nested() into a single list
301 # assigned to foo.
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000302 with Nested(m) as foo:
Tim Peters400cbc32006-02-28 18:44:41 +0000303 self.assertInWithManagerInvariants(m)
304 self.assertAfterWithManagerInvariantsNoError(m)
305
306 def testSingleArgBoundToSingleElementParenthesizedList(self):
307 m = mock_contextmanager_generator()
308 # This will bind all the arguments to nested() into a single list
309 # assigned to foo.
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000310 with Nested(m) as (foo):
Tim Peters400cbc32006-02-28 18:44:41 +0000311 self.assertInWithManagerInvariants(m)
312 self.assertAfterWithManagerInvariantsNoError(m)
313
314 def testSingleArgBoundToMultipleElementTupleError(self):
315 def shouldThrowValueError():
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000316 with Nested(mock_contextmanager_generator()) as (foo, bar):
Tim Peters400cbc32006-02-28 18:44:41 +0000317 pass
318 self.assertRaises(ValueError, shouldThrowValueError)
319
320 def testSingleArgUnbound(self):
321 mock_contextmanager = mock_contextmanager_generator()
322 mock_nested = MockNested(mock_contextmanager)
323 with mock_nested:
324 self.assertInWithManagerInvariants(mock_contextmanager)
325 self.assertInWithManagerInvariants(mock_nested)
326 self.assertAfterWithManagerInvariantsNoError(mock_contextmanager)
327 self.assertAfterWithManagerInvariantsNoError(mock_nested)
328
329 def testMultipleArgUnbound(self):
330 m = mock_contextmanager_generator()
331 n = mock_contextmanager_generator()
332 o = mock_contextmanager_generator()
333 mock_nested = MockNested(m, n, o)
334 with mock_nested:
335 self.assertInWithManagerInvariants(m)
336 self.assertInWithManagerInvariants(n)
337 self.assertInWithManagerInvariants(o)
338 self.assertInWithManagerInvariants(mock_nested)
339 self.assertAfterWithManagerInvariantsNoError(m)
340 self.assertAfterWithManagerInvariantsNoError(n)
341 self.assertAfterWithManagerInvariantsNoError(o)
342 self.assertAfterWithManagerInvariantsNoError(mock_nested)
343
344 def testMultipleArgBound(self):
345 mock_nested = MockNested(mock_contextmanager_generator(),
346 mock_contextmanager_generator(), mock_contextmanager_generator())
347 with mock_nested as (m, n, o):
348 self.assertInWithGeneratorInvariants(m)
349 self.assertInWithGeneratorInvariants(n)
350 self.assertInWithGeneratorInvariants(o)
351 self.assertInWithManagerInvariants(mock_nested)
352 self.assertAfterWithGeneratorInvariantsNoError(m)
353 self.assertAfterWithGeneratorInvariantsNoError(n)
354 self.assertAfterWithGeneratorInvariantsNoError(o)
355 self.assertAfterWithManagerInvariantsNoError(mock_nested)
356
357
Collin Winterba21f612007-09-01 20:29:04 +0000358class ExceptionalTestCase(ContextmanagerAssertionMixin, unittest.TestCase):
Tim Peters400cbc32006-02-28 18:44:41 +0000359 def testSingleResource(self):
360 cm = mock_contextmanager_generator()
361 def shouldThrow():
362 with cm as self.resource:
363 self.assertInWithManagerInvariants(cm)
364 self.assertInWithGeneratorInvariants(self.resource)
365 self.raiseTestException()
366 self.assertRaises(RuntimeError, shouldThrow)
367 self.assertAfterWithManagerInvariantsWithError(cm)
368 self.assertAfterWithGeneratorInvariantsWithError(self.resource)
369
370 def testNestedSingleStatements(self):
371 mock_a = mock_contextmanager_generator()
372 mock_b = mock_contextmanager_generator()
373 def shouldThrow():
374 with mock_a as self.foo:
375 with mock_b as self.bar:
376 self.assertInWithManagerInvariants(mock_a)
377 self.assertInWithManagerInvariants(mock_b)
378 self.assertInWithGeneratorInvariants(self.foo)
379 self.assertInWithGeneratorInvariants(self.bar)
380 self.raiseTestException()
381 self.assertRaises(RuntimeError, shouldThrow)
382 self.assertAfterWithManagerInvariantsWithError(mock_a)
383 self.assertAfterWithManagerInvariantsWithError(mock_b)
384 self.assertAfterWithGeneratorInvariantsWithError(self.foo)
385 self.assertAfterWithGeneratorInvariantsWithError(self.bar)
386
387 def testMultipleResourcesInSingleStatement(self):
388 cm_a = mock_contextmanager_generator()
389 cm_b = mock_contextmanager_generator()
390 mock_nested = MockNested(cm_a, cm_b)
391 def shouldThrow():
392 with mock_nested as (self.resource_a, self.resource_b):
393 self.assertInWithManagerInvariants(cm_a)
394 self.assertInWithManagerInvariants(cm_b)
395 self.assertInWithManagerInvariants(mock_nested)
396 self.assertInWithGeneratorInvariants(self.resource_a)
397 self.assertInWithGeneratorInvariants(self.resource_b)
398 self.raiseTestException()
399 self.assertRaises(RuntimeError, shouldThrow)
400 self.assertAfterWithManagerInvariantsWithError(cm_a)
401 self.assertAfterWithManagerInvariantsWithError(cm_b)
402 self.assertAfterWithManagerInvariantsWithError(mock_nested)
403 self.assertAfterWithGeneratorInvariantsWithError(self.resource_a)
404 self.assertAfterWithGeneratorInvariantsWithError(self.resource_b)
405
406 def testNestedExceptionBeforeInnerStatement(self):
407 mock_a = mock_contextmanager_generator()
408 mock_b = mock_contextmanager_generator()
409 self.bar = None
410 def shouldThrow():
411 with mock_a as self.foo:
412 self.assertInWithManagerInvariants(mock_a)
413 self.assertInWithGeneratorInvariants(self.foo)
414 self.raiseTestException()
415 with mock_b as self.bar:
416 pass
417 self.assertRaises(RuntimeError, shouldThrow)
418 self.assertAfterWithManagerInvariantsWithError(mock_a)
419 self.assertAfterWithGeneratorInvariantsWithError(self.foo)
420
421 # The inner statement stuff should never have been touched
422 self.assertEqual(self.bar, None)
Tim Peters400cbc32006-02-28 18:44:41 +0000423 self.assertFalse(mock_b.enter_called)
424 self.assertFalse(mock_b.exit_called)
425 self.assertEqual(mock_b.exit_args, None)
426
427 def testNestedExceptionAfterInnerStatement(self):
428 mock_a = mock_contextmanager_generator()
429 mock_b = mock_contextmanager_generator()
430 def shouldThrow():
431 with mock_a as self.foo:
432 with mock_b as self.bar:
433 self.assertInWithManagerInvariants(mock_a)
434 self.assertInWithManagerInvariants(mock_b)
435 self.assertInWithGeneratorInvariants(self.foo)
436 self.assertInWithGeneratorInvariants(self.bar)
437 self.raiseTestException()
438 self.assertRaises(RuntimeError, shouldThrow)
439 self.assertAfterWithManagerInvariantsWithError(mock_a)
440 self.assertAfterWithManagerInvariantsNoError(mock_b)
441 self.assertAfterWithGeneratorInvariantsWithError(self.foo)
442 self.assertAfterWithGeneratorInvariantsNoError(self.bar)
443
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000444 def testRaisedStopIteration1(self):
Guido van Rossum2cc30da2007-11-02 23:46:40 +0000445 # From bug 1462485
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000446 @contextmanager
447 def cm():
448 yield
449
450 def shouldThrow():
451 with cm():
452 raise StopIteration("from with")
453
454 self.assertRaises(StopIteration, shouldThrow)
455
456 def testRaisedStopIteration2(self):
Guido van Rossum2cc30da2007-11-02 23:46:40 +0000457 # From bug 1462485
Thomas Wouters477c8d52006-05-27 19:21:47 +0000458 class cm(object):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000459 def __enter__(self):
460 pass
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000461 def __exit__(self, type, value, traceback):
462 pass
463
464 def shouldThrow():
465 with cm():
466 raise StopIteration("from with")
467
468 self.assertRaises(StopIteration, shouldThrow)
469
Guido van Rossum2cc30da2007-11-02 23:46:40 +0000470 def testRaisedStopIteration3(self):
471 # Another variant where the exception hasn't been instantiated
472 # From bug 1705170
473 @contextmanager
474 def cm():
475 yield
476
477 def shouldThrow():
478 with cm():
479 raise next(iter([]))
480
481 self.assertRaises(StopIteration, shouldThrow)
482
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000483 def testRaisedGeneratorExit1(self):
Guido van Rossum2cc30da2007-11-02 23:46:40 +0000484 # From bug 1462485
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000485 @contextmanager
486 def cm():
487 yield
488
489 def shouldThrow():
490 with cm():
491 raise GeneratorExit("from with")
492
493 self.assertRaises(GeneratorExit, shouldThrow)
494
495 def testRaisedGeneratorExit2(self):
Guido van Rossum2cc30da2007-11-02 23:46:40 +0000496 # From bug 1462485
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000497 class cm (object):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000498 def __enter__(self):
499 pass
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000500 def __exit__(self, type, value, traceback):
501 pass
502
503 def shouldThrow():
504 with cm():
505 raise GeneratorExit("from with")
506
507 self.assertRaises(GeneratorExit, shouldThrow)
508
Tim Peters400cbc32006-02-28 18:44:41 +0000509
510class NonLocalFlowControlTestCase(unittest.TestCase):
511
512 def testWithBreak(self):
513 counter = 0
514 while True:
515 counter += 1
516 with mock_contextmanager_generator():
517 counter += 10
518 break
519 counter += 100 # Not reached
520 self.assertEqual(counter, 11)
521
522 def testWithContinue(self):
523 counter = 0
524 while True:
525 counter += 1
526 if counter > 2:
527 break
528 with mock_contextmanager_generator():
529 counter += 10
530 continue
531 counter += 100 # Not reached
532 self.assertEqual(counter, 12)
533
534 def testWithReturn(self):
535 def foo():
536 counter = 0
537 while True:
538 counter += 1
539 with mock_contextmanager_generator():
540 counter += 10
541 return counter
542 counter += 100 # Not reached
543 self.assertEqual(foo(), 11)
544
545 def testWithYield(self):
546 def gen():
547 with mock_contextmanager_generator():
548 yield 12
549 yield 13
550 x = list(gen())
551 self.assertEqual(x, [12, 13])
552
553 def testWithRaise(self):
554 counter = 0
555 try:
556 counter += 1
557 with mock_contextmanager_generator():
558 counter += 10
559 raise RuntimeError
560 counter += 100 # Not reached
561 except RuntimeError:
562 self.assertEqual(counter, 11)
563 else:
564 self.fail("Didn't raise RuntimeError")
565
566
567class AssignmentTargetTestCase(unittest.TestCase):
568
569 def testSingleComplexTarget(self):
570 targets = {1: [0, 1, 2]}
571 with mock_contextmanager_generator() as targets[1][0]:
Guido van Rossum87b63952007-02-11 07:05:21 +0000572 self.assertEqual(list(targets.keys()), [1])
Tim Peters400cbc32006-02-28 18:44:41 +0000573 self.assertEqual(targets[1][0].__class__, MockResource)
Guido van Rossum87b63952007-02-11 07:05:21 +0000574 with mock_contextmanager_generator() as list(targets.values())[0][1]:
575 self.assertEqual(list(targets.keys()), [1])
Tim Peters400cbc32006-02-28 18:44:41 +0000576 self.assertEqual(targets[1][1].__class__, MockResource)
577 with mock_contextmanager_generator() as targets[2]:
Guido van Rossum87b63952007-02-11 07:05:21 +0000578 keys = list(targets.keys())
Tim Peters400cbc32006-02-28 18:44:41 +0000579 keys.sort()
580 self.assertEqual(keys, [1, 2])
581 class C: pass
582 blah = C()
583 with mock_contextmanager_generator() as blah.foo:
584 self.assertEqual(hasattr(blah, "foo"), True)
585
586 def testMultipleComplexTargets(self):
587 class C:
Tim Peters400cbc32006-02-28 18:44:41 +0000588 def __enter__(self): return 1, 2, 3
Guido van Rossumf6694362006-03-10 02:28:35 +0000589 def __exit__(self, t, v, tb): pass
Tim Peters400cbc32006-02-28 18:44:41 +0000590 targets = {1: [0, 1, 2]}
591 with C() as (targets[1][0], targets[1][1], targets[1][2]):
592 self.assertEqual(targets, {1: [1, 2, 3]})
Guido van Rossum87b63952007-02-11 07:05:21 +0000593 with C() as (list(targets.values())[0][2], list(targets.values())[0][1], list(targets.values())[0][0]):
Tim Peters400cbc32006-02-28 18:44:41 +0000594 self.assertEqual(targets, {1: [3, 2, 1]})
595 with C() as (targets[1], targets[2], targets[3]):
596 self.assertEqual(targets, {1: 1, 2: 2, 3: 3})
597 class B: pass
598 blah = B()
599 with C() as (blah.one, blah.two, blah.three):
600 self.assertEqual(blah.one, 1)
601 self.assertEqual(blah.two, 2)
602 self.assertEqual(blah.three, 3)
603
604
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000605class ExitSwallowsExceptionTestCase(unittest.TestCase):
606
Guido van Rossumf6694362006-03-10 02:28:35 +0000607 def testExitTrueSwallowsException(self):
608 class AfricanSwallow:
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000609 def __enter__(self): pass
Guido van Rossumf6694362006-03-10 02:28:35 +0000610 def __exit__(self, t, v, tb): return True
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000611 try:
Guido van Rossumf6694362006-03-10 02:28:35 +0000612 with AfricanSwallow():
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000613 1/0
614 except ZeroDivisionError:
615 self.fail("ZeroDivisionError should have been swallowed")
616
Guido van Rossumf6694362006-03-10 02:28:35 +0000617 def testExitFalseDoesntSwallowException(self):
618 class EuropeanSwallow:
Guido van Rossumf6694362006-03-10 02:28:35 +0000619 def __enter__(self): pass
620 def __exit__(self, t, v, tb): return False
621 try:
622 with EuropeanSwallow():
623 1/0
624 except ZeroDivisionError:
625 pass
626 else:
627 self.fail("ZeroDivisionError should have been raised")
628
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000629
Tim Peters400cbc32006-02-28 18:44:41 +0000630def test_main():
631 run_unittest(FailureTestCase, NonexceptionalTestCase,
632 NestedNonexceptionalTestCase, ExceptionalTestCase,
633 NonLocalFlowControlTestCase,
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000634 AssignmentTargetTestCase,
635 ExitSwallowsExceptionTestCase)
Tim Peters400cbc32006-02-28 18:44:41 +0000636
637
638if __name__ == '__main__':
639 test_main()