blob: 3ba897798bf7065c5785080d19209931a03c00c5 [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
Benjamin Petersond1c7d072008-09-25 20:46:05 +000012import StringIO
Guido van Rossum1a5e21e2006-02-28 21:57:43 +000013from collections import deque
Nick Coghlanafd5e632006-05-03 13:02:47 +000014from contextlib import GeneratorContextManager, contextmanager
Tim Peters400cbc32006-02-28 18:44:41 +000015from test.test_support import run_unittest
16
17
Nick Coghlanafd5e632006-05-03 13:02:47 +000018class MockContextManager(GeneratorContextManager):
Tim Peters400cbc32006-02-28 18:44:41 +000019 def __init__(self, gen):
Nick Coghlanafd5e632006-05-03 13:02:47 +000020 GeneratorContextManager.__init__(self, gen)
Tim Peters400cbc32006-02-28 18:44:41 +000021 self.enter_called = False
22 self.exit_called = False
23 self.exit_args = None
24
Tim Peters400cbc32006-02-28 18:44:41 +000025 def __enter__(self):
26 self.enter_called = True
Nick Coghlanafd5e632006-05-03 13:02:47 +000027 return GeneratorContextManager.__enter__(self)
Tim Peters400cbc32006-02-28 18:44:41 +000028
29 def __exit__(self, type, value, traceback):
30 self.exit_called = True
31 self.exit_args = (type, value, traceback)
Nick Coghlanafd5e632006-05-03 13:02:47 +000032 return GeneratorContextManager.__exit__(self, type,
33 value, traceback)
Tim Peters400cbc32006-02-28 18:44:41 +000034
35
36def mock_contextmanager(func):
37 def helper(*args, **kwds):
38 return MockContextManager(func(*args, **kwds))
39 return helper
40
41
42class MockResource(object):
43 def __init__(self):
44 self.yielded = False
45 self.stopped = False
46
47
48@mock_contextmanager
49def mock_contextmanager_generator():
50 mock = MockResource()
51 try:
52 mock.yielded = True
53 yield mock
54 finally:
55 mock.stopped = True
56
57
Guido van Rossum1a5e21e2006-02-28 21:57:43 +000058class Nested(object):
59
Guido van Rossumda5b7012006-05-02 19:47:52 +000060 def __init__(self, *managers):
61 self.managers = managers
Guido van Rossum1a5e21e2006-02-28 21:57:43 +000062 self.entered = None
63
Guido van Rossum1a5e21e2006-02-28 21:57:43 +000064 def __enter__(self):
65 if self.entered is not None:
66 raise RuntimeError("Context is not reentrant")
67 self.entered = deque()
68 vars = []
69 try:
Guido van Rossumda5b7012006-05-02 19:47:52 +000070 for mgr in self.managers:
Guido van Rossum1a5e21e2006-02-28 21:57:43 +000071 vars.append(mgr.__enter__())
72 self.entered.appendleft(mgr)
73 except:
Guido van Rossumf6694362006-03-10 02:28:35 +000074 if not self.__exit__(*sys.exc_info()):
75 raise
Guido van Rossum1a5e21e2006-02-28 21:57:43 +000076 return vars
77
78 def __exit__(self, *exc_info):
79 # Behave like nested with statements
80 # first in, last out
81 # New exceptions override old ones
82 ex = exc_info
83 for mgr in self.entered:
84 try:
Guido van Rossumf6694362006-03-10 02:28:35 +000085 if mgr.__exit__(*ex):
86 ex = (None, None, None)
Guido van Rossum1a5e21e2006-02-28 21:57:43 +000087 except:
88 ex = sys.exc_info()
89 self.entered = None
90 if ex is not exc_info:
91 raise ex[0], ex[1], ex[2]
92
93
94class MockNested(Nested):
Guido van Rossumda5b7012006-05-02 19:47:52 +000095 def __init__(self, *managers):
96 Nested.__init__(self, *managers)
Tim Peters400cbc32006-02-28 18:44:41 +000097 self.enter_called = False
98 self.exit_called = False
99 self.exit_args = None
100
Tim Peters400cbc32006-02-28 18:44:41 +0000101 def __enter__(self):
102 self.enter_called = True
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000103 return Nested.__enter__(self)
Tim Peters400cbc32006-02-28 18:44:41 +0000104
105 def __exit__(self, *exc_info):
106 self.exit_called = True
107 self.exit_args = exc_info
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000108 return Nested.__exit__(self, *exc_info)
Tim Peters400cbc32006-02-28 18:44:41 +0000109
110
111class FailureTestCase(unittest.TestCase):
112 def testNameError(self):
113 def fooNotDeclared():
114 with foo: pass
115 self.assertRaises(NameError, fooNotDeclared)
116
Tim Peters400cbc32006-02-28 18:44:41 +0000117 def testEnterAttributeError(self):
118 class LacksEnter(object):
Tim Peters400cbc32006-02-28 18:44:41 +0000119 def __exit__(self, type, value, traceback):
120 pass
121
122 def fooLacksEnter():
123 foo = LacksEnter()
124 with foo: pass
125 self.assertRaises(AttributeError, fooLacksEnter)
126
127 def testExitAttributeError(self):
128 class LacksExit(object):
Tim Peters400cbc32006-02-28 18:44:41 +0000129 def __enter__(self):
130 pass
131
132 def fooLacksExit():
133 foo = LacksExit()
134 with foo: pass
135 self.assertRaises(AttributeError, fooLacksExit)
136
137 def assertRaisesSyntaxError(self, codestr):
138 def shouldRaiseSyntaxError(s):
139 compile(s, '', 'single')
140 self.assertRaises(SyntaxError, shouldRaiseSyntaxError, codestr)
141
142 def testAssignmentToNoneError(self):
143 self.assertRaisesSyntaxError('with mock as None:\n pass')
144 self.assertRaisesSyntaxError(
145 'with mock as (None):\n'
146 ' pass')
147
148 def testAssignmentToEmptyTupleError(self):
149 self.assertRaisesSyntaxError(
150 'with mock as ():\n'
151 ' pass')
152
153 def testAssignmentToTupleOnlyContainingNoneError(self):
154 self.assertRaisesSyntaxError('with mock as None,:\n pass')
155 self.assertRaisesSyntaxError(
156 'with mock as (None,):\n'
157 ' pass')
158
159 def testAssignmentToTupleContainingNoneError(self):
160 self.assertRaisesSyntaxError(
161 'with mock as (foo, None, bar):\n'
162 ' pass')
163
Tim Peters400cbc32006-02-28 18:44:41 +0000164 def testEnterThrows(self):
165 class EnterThrows(object):
Tim Peters400cbc32006-02-28 18:44:41 +0000166 def __enter__(self):
Guido van Rossumda5b7012006-05-02 19:47:52 +0000167 raise RuntimeError("Enter threw")
Tim Peters400cbc32006-02-28 18:44:41 +0000168 def __exit__(self, *args):
169 pass
170
171 def shouldThrow():
172 ct = EnterThrows()
173 self.foo = None
174 with ct as self.foo:
175 pass
176 self.assertRaises(RuntimeError, shouldThrow)
177 self.assertEqual(self.foo, None)
178
179 def testExitThrows(self):
180 class ExitThrows(object):
Tim Peters400cbc32006-02-28 18:44:41 +0000181 def __enter__(self):
182 return
183 def __exit__(self, *args):
184 raise RuntimeError(42)
185 def shouldThrow():
186 with ExitThrows():
187 pass
188 self.assertRaises(RuntimeError, shouldThrow)
189
190class ContextmanagerAssertionMixin(object):
191 TEST_EXCEPTION = RuntimeError("test exception")
192
193 def assertInWithManagerInvariants(self, mock_manager):
Tim Peters400cbc32006-02-28 18:44:41 +0000194 self.assertTrue(mock_manager.enter_called)
195 self.assertFalse(mock_manager.exit_called)
196 self.assertEqual(mock_manager.exit_args, None)
197
198 def assertAfterWithManagerInvariants(self, mock_manager, exit_args):
Tim Peters400cbc32006-02-28 18:44:41 +0000199 self.assertTrue(mock_manager.enter_called)
200 self.assertTrue(mock_manager.exit_called)
201 self.assertEqual(mock_manager.exit_args, exit_args)
202
203 def assertAfterWithManagerInvariantsNoError(self, mock_manager):
204 self.assertAfterWithManagerInvariants(mock_manager,
205 (None, None, None))
206
207 def assertInWithGeneratorInvariants(self, mock_generator):
208 self.assertTrue(mock_generator.yielded)
209 self.assertFalse(mock_generator.stopped)
210
211 def assertAfterWithGeneratorInvariantsNoError(self, mock_generator):
212 self.assertTrue(mock_generator.yielded)
213 self.assertTrue(mock_generator.stopped)
214
215 def raiseTestException(self):
216 raise self.TEST_EXCEPTION
217
218 def assertAfterWithManagerInvariantsWithError(self, mock_manager):
Tim Peters400cbc32006-02-28 18:44:41 +0000219 self.assertTrue(mock_manager.enter_called)
220 self.assertTrue(mock_manager.exit_called)
221 self.assertEqual(mock_manager.exit_args[0], RuntimeError)
222 self.assertEqual(mock_manager.exit_args[1], self.TEST_EXCEPTION)
223
224 def assertAfterWithGeneratorInvariantsWithError(self, mock_generator):
225 self.assertTrue(mock_generator.yielded)
226 self.assertTrue(mock_generator.stopped)
227
228
229class NonexceptionalTestCase(unittest.TestCase, ContextmanagerAssertionMixin):
230 def testInlineGeneratorSyntax(self):
231 with mock_contextmanager_generator():
232 pass
233
234 def testUnboundGenerator(self):
235 mock = mock_contextmanager_generator()
236 with mock:
237 pass
238 self.assertAfterWithManagerInvariantsNoError(mock)
239
240 def testInlineGeneratorBoundSyntax(self):
241 with mock_contextmanager_generator() as foo:
242 self.assertInWithGeneratorInvariants(foo)
243 # FIXME: In the future, we'll try to keep the bound names from leaking
244 self.assertAfterWithGeneratorInvariantsNoError(foo)
245
246 def testInlineGeneratorBoundToExistingVariable(self):
247 foo = None
248 with mock_contextmanager_generator() as foo:
249 self.assertInWithGeneratorInvariants(foo)
250 self.assertAfterWithGeneratorInvariantsNoError(foo)
251
252 def testInlineGeneratorBoundToDottedVariable(self):
253 with mock_contextmanager_generator() as self.foo:
254 self.assertInWithGeneratorInvariants(self.foo)
255 self.assertAfterWithGeneratorInvariantsNoError(self.foo)
256
257 def testBoundGenerator(self):
258 mock = mock_contextmanager_generator()
259 with mock as foo:
260 self.assertInWithGeneratorInvariants(foo)
261 self.assertInWithManagerInvariants(mock)
262 self.assertAfterWithGeneratorInvariantsNoError(foo)
263 self.assertAfterWithManagerInvariantsNoError(mock)
264
265 def testNestedSingleStatements(self):
266 mock_a = mock_contextmanager_generator()
267 with mock_a as foo:
268 mock_b = mock_contextmanager_generator()
269 with mock_b as bar:
270 self.assertInWithManagerInvariants(mock_a)
271 self.assertInWithManagerInvariants(mock_b)
272 self.assertInWithGeneratorInvariants(foo)
273 self.assertInWithGeneratorInvariants(bar)
274 self.assertAfterWithManagerInvariantsNoError(mock_b)
275 self.assertAfterWithGeneratorInvariantsNoError(bar)
276 self.assertInWithManagerInvariants(mock_a)
277 self.assertInWithGeneratorInvariants(foo)
278 self.assertAfterWithManagerInvariantsNoError(mock_a)
279 self.assertAfterWithGeneratorInvariantsNoError(foo)
280
281
282class NestedNonexceptionalTestCase(unittest.TestCase,
283 ContextmanagerAssertionMixin):
284 def testSingleArgInlineGeneratorSyntax(self):
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000285 with Nested(mock_contextmanager_generator()):
Tim Peters400cbc32006-02-28 18:44:41 +0000286 pass
287
288 def testSingleArgUnbound(self):
289 mock_contextmanager = mock_contextmanager_generator()
290 mock_nested = MockNested(mock_contextmanager)
291 with mock_nested:
292 self.assertInWithManagerInvariants(mock_contextmanager)
293 self.assertInWithManagerInvariants(mock_nested)
294 self.assertAfterWithManagerInvariantsNoError(mock_contextmanager)
295 self.assertAfterWithManagerInvariantsNoError(mock_nested)
296
297 def testSingleArgBoundToNonTuple(self):
298 m = mock_contextmanager_generator()
299 # This will bind all the arguments to nested() into a single list
300 # assigned to foo.
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000301 with Nested(m) as foo:
Tim Peters400cbc32006-02-28 18:44:41 +0000302 self.assertInWithManagerInvariants(m)
303 self.assertAfterWithManagerInvariantsNoError(m)
304
305 def testSingleArgBoundToSingleElementParenthesizedList(self):
306 m = mock_contextmanager_generator()
307 # This will bind all the arguments to nested() into a single list
308 # assigned to foo.
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000309 with Nested(m) as (foo):
Tim Peters400cbc32006-02-28 18:44:41 +0000310 self.assertInWithManagerInvariants(m)
311 self.assertAfterWithManagerInvariantsNoError(m)
312
313 def testSingleArgBoundToMultipleElementTupleError(self):
314 def shouldThrowValueError():
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000315 with Nested(mock_contextmanager_generator()) as (foo, bar):
Tim Peters400cbc32006-02-28 18:44:41 +0000316 pass
317 self.assertRaises(ValueError, shouldThrowValueError)
318
319 def testSingleArgUnbound(self):
320 mock_contextmanager = mock_contextmanager_generator()
321 mock_nested = MockNested(mock_contextmanager)
322 with mock_nested:
323 self.assertInWithManagerInvariants(mock_contextmanager)
324 self.assertInWithManagerInvariants(mock_nested)
325 self.assertAfterWithManagerInvariantsNoError(mock_contextmanager)
326 self.assertAfterWithManagerInvariantsNoError(mock_nested)
327
328 def testMultipleArgUnbound(self):
329 m = mock_contextmanager_generator()
330 n = mock_contextmanager_generator()
331 o = mock_contextmanager_generator()
332 mock_nested = MockNested(m, n, o)
333 with mock_nested:
334 self.assertInWithManagerInvariants(m)
335 self.assertInWithManagerInvariants(n)
336 self.assertInWithManagerInvariants(o)
337 self.assertInWithManagerInvariants(mock_nested)
338 self.assertAfterWithManagerInvariantsNoError(m)
339 self.assertAfterWithManagerInvariantsNoError(n)
340 self.assertAfterWithManagerInvariantsNoError(o)
341 self.assertAfterWithManagerInvariantsNoError(mock_nested)
342
343 def testMultipleArgBound(self):
344 mock_nested = MockNested(mock_contextmanager_generator(),
345 mock_contextmanager_generator(), mock_contextmanager_generator())
346 with mock_nested as (m, n, o):
347 self.assertInWithGeneratorInvariants(m)
348 self.assertInWithGeneratorInvariants(n)
349 self.assertInWithGeneratorInvariants(o)
350 self.assertInWithManagerInvariants(mock_nested)
351 self.assertAfterWithGeneratorInvariantsNoError(m)
352 self.assertAfterWithGeneratorInvariantsNoError(n)
353 self.assertAfterWithGeneratorInvariantsNoError(o)
354 self.assertAfterWithManagerInvariantsNoError(mock_nested)
355
356
357class ExceptionalTestCase(unittest.TestCase, ContextmanagerAssertionMixin):
358 def testSingleResource(self):
359 cm = mock_contextmanager_generator()
360 def shouldThrow():
361 with cm as self.resource:
362 self.assertInWithManagerInvariants(cm)
363 self.assertInWithGeneratorInvariants(self.resource)
364 self.raiseTestException()
365 self.assertRaises(RuntimeError, shouldThrow)
366 self.assertAfterWithManagerInvariantsWithError(cm)
367 self.assertAfterWithGeneratorInvariantsWithError(self.resource)
368
369 def testNestedSingleStatements(self):
370 mock_a = mock_contextmanager_generator()
371 mock_b = mock_contextmanager_generator()
372 def shouldThrow():
373 with mock_a as self.foo:
374 with mock_b as self.bar:
375 self.assertInWithManagerInvariants(mock_a)
376 self.assertInWithManagerInvariants(mock_b)
377 self.assertInWithGeneratorInvariants(self.foo)
378 self.assertInWithGeneratorInvariants(self.bar)
379 self.raiseTestException()
380 self.assertRaises(RuntimeError, shouldThrow)
381 self.assertAfterWithManagerInvariantsWithError(mock_a)
382 self.assertAfterWithManagerInvariantsWithError(mock_b)
383 self.assertAfterWithGeneratorInvariantsWithError(self.foo)
384 self.assertAfterWithGeneratorInvariantsWithError(self.bar)
385
386 def testMultipleResourcesInSingleStatement(self):
387 cm_a = mock_contextmanager_generator()
388 cm_b = mock_contextmanager_generator()
389 mock_nested = MockNested(cm_a, cm_b)
390 def shouldThrow():
391 with mock_nested as (self.resource_a, self.resource_b):
392 self.assertInWithManagerInvariants(cm_a)
393 self.assertInWithManagerInvariants(cm_b)
394 self.assertInWithManagerInvariants(mock_nested)
395 self.assertInWithGeneratorInvariants(self.resource_a)
396 self.assertInWithGeneratorInvariants(self.resource_b)
397 self.raiseTestException()
398 self.assertRaises(RuntimeError, shouldThrow)
399 self.assertAfterWithManagerInvariantsWithError(cm_a)
400 self.assertAfterWithManagerInvariantsWithError(cm_b)
401 self.assertAfterWithManagerInvariantsWithError(mock_nested)
402 self.assertAfterWithGeneratorInvariantsWithError(self.resource_a)
403 self.assertAfterWithGeneratorInvariantsWithError(self.resource_b)
404
405 def testNestedExceptionBeforeInnerStatement(self):
406 mock_a = mock_contextmanager_generator()
407 mock_b = mock_contextmanager_generator()
408 self.bar = None
409 def shouldThrow():
410 with mock_a as self.foo:
411 self.assertInWithManagerInvariants(mock_a)
412 self.assertInWithGeneratorInvariants(self.foo)
413 self.raiseTestException()
414 with mock_b as self.bar:
415 pass
416 self.assertRaises(RuntimeError, shouldThrow)
417 self.assertAfterWithManagerInvariantsWithError(mock_a)
418 self.assertAfterWithGeneratorInvariantsWithError(self.foo)
419
420 # The inner statement stuff should never have been touched
421 self.assertEqual(self.bar, None)
Tim Peters400cbc32006-02-28 18:44:41 +0000422 self.assertFalse(mock_b.enter_called)
423 self.assertFalse(mock_b.exit_called)
424 self.assertEqual(mock_b.exit_args, None)
425
426 def testNestedExceptionAfterInnerStatement(self):
427 mock_a = mock_contextmanager_generator()
428 mock_b = mock_contextmanager_generator()
429 def shouldThrow():
430 with mock_a as self.foo:
431 with mock_b as self.bar:
432 self.assertInWithManagerInvariants(mock_a)
433 self.assertInWithManagerInvariants(mock_b)
434 self.assertInWithGeneratorInvariants(self.foo)
435 self.assertInWithGeneratorInvariants(self.bar)
436 self.raiseTestException()
437 self.assertRaises(RuntimeError, shouldThrow)
438 self.assertAfterWithManagerInvariantsWithError(mock_a)
439 self.assertAfterWithManagerInvariantsNoError(mock_b)
440 self.assertAfterWithGeneratorInvariantsWithError(self.foo)
441 self.assertAfterWithGeneratorInvariantsNoError(self.bar)
442
Phillip J. Eby9444bd52006-04-03 20:05:05 +0000443 def testRaisedStopIteration1(self):
Nick Coghlane53fcfd2007-11-07 12:26:40 +0000444 # From bug 1462485
Nick Coghlanafd5e632006-05-03 13:02:47 +0000445 @contextmanager
Phillip J. Eby9444bd52006-04-03 20:05:05 +0000446 def cm():
447 yield
448
449 def shouldThrow():
450 with cm():
451 raise StopIteration("from with")
452
453 self.assertRaises(StopIteration, shouldThrow)
454
455 def testRaisedStopIteration2(self):
Nick Coghlane53fcfd2007-11-07 12:26:40 +0000456 # From bug 1462485
Guido van Rossumda5b7012006-05-02 19:47:52 +0000457 class cm(object):
Phillip J. Eby9444bd52006-04-03 20:05:05 +0000458 def __enter__(self):
459 pass
Phillip J. Eby9444bd52006-04-03 20:05:05 +0000460 def __exit__(self, type, value, traceback):
461 pass
462
463 def shouldThrow():
464 with cm():
465 raise StopIteration("from with")
466
467 self.assertRaises(StopIteration, shouldThrow)
468
Nick Coghlane53fcfd2007-11-07 12:26:40 +0000469 def testRaisedStopIteration3(self):
470 # Another variant where the exception hasn't been instantiated
471 # From bug 1705170
472 @contextmanager
473 def cm():
474 yield
475
476 def shouldThrow():
477 with cm():
478 raise iter([]).next()
479
480 self.assertRaises(StopIteration, shouldThrow)
481
Phillip J. Eby9444bd52006-04-03 20:05:05 +0000482 def testRaisedGeneratorExit1(self):
Nick Coghlane53fcfd2007-11-07 12:26:40 +0000483 # From bug 1462485
Nick Coghlanafd5e632006-05-03 13:02:47 +0000484 @contextmanager
Phillip J. Eby9444bd52006-04-03 20:05:05 +0000485 def cm():
486 yield
487
488 def shouldThrow():
489 with cm():
490 raise GeneratorExit("from with")
491
492 self.assertRaises(GeneratorExit, shouldThrow)
493
494 def testRaisedGeneratorExit2(self):
Nick Coghlane53fcfd2007-11-07 12:26:40 +0000495 # From bug 1462485
Phillip J. Eby9444bd52006-04-03 20:05:05 +0000496 class cm (object):
Phillip J. Eby9444bd52006-04-03 20:05:05 +0000497 def __enter__(self):
498 pass
Phillip J. Eby9444bd52006-04-03 20:05:05 +0000499 def __exit__(self, type, value, traceback):
500 pass
501
502 def shouldThrow():
503 with cm():
504 raise GeneratorExit("from with")
505
506 self.assertRaises(GeneratorExit, shouldThrow)
507
Tim Peters400cbc32006-02-28 18:44:41 +0000508
509class NonLocalFlowControlTestCase(unittest.TestCase):
510
511 def testWithBreak(self):
512 counter = 0
513 while True:
514 counter += 1
515 with mock_contextmanager_generator():
516 counter += 10
517 break
518 counter += 100 # Not reached
519 self.assertEqual(counter, 11)
520
521 def testWithContinue(self):
522 counter = 0
523 while True:
524 counter += 1
525 if counter > 2:
526 break
527 with mock_contextmanager_generator():
528 counter += 10
529 continue
530 counter += 100 # Not reached
531 self.assertEqual(counter, 12)
532
533 def testWithReturn(self):
534 def foo():
535 counter = 0
536 while True:
537 counter += 1
538 with mock_contextmanager_generator():
539 counter += 10
540 return counter
541 counter += 100 # Not reached
542 self.assertEqual(foo(), 11)
543
544 def testWithYield(self):
545 def gen():
546 with mock_contextmanager_generator():
547 yield 12
548 yield 13
549 x = list(gen())
550 self.assertEqual(x, [12, 13])
551
552 def testWithRaise(self):
553 counter = 0
554 try:
555 counter += 1
556 with mock_contextmanager_generator():
557 counter += 10
558 raise RuntimeError
559 counter += 100 # Not reached
560 except RuntimeError:
561 self.assertEqual(counter, 11)
562 else:
563 self.fail("Didn't raise RuntimeError")
564
565
566class AssignmentTargetTestCase(unittest.TestCase):
567
568 def testSingleComplexTarget(self):
569 targets = {1: [0, 1, 2]}
570 with mock_contextmanager_generator() as targets[1][0]:
571 self.assertEqual(targets.keys(), [1])
572 self.assertEqual(targets[1][0].__class__, MockResource)
573 with mock_contextmanager_generator() as targets.values()[0][1]:
574 self.assertEqual(targets.keys(), [1])
575 self.assertEqual(targets[1][1].__class__, MockResource)
576 with mock_contextmanager_generator() as targets[2]:
577 keys = targets.keys()
578 keys.sort()
579 self.assertEqual(keys, [1, 2])
580 class C: pass
581 blah = C()
582 with mock_contextmanager_generator() as blah.foo:
583 self.assertEqual(hasattr(blah, "foo"), True)
584
585 def testMultipleComplexTargets(self):
586 class C:
Tim Peters400cbc32006-02-28 18:44:41 +0000587 def __enter__(self): return 1, 2, 3
Guido van Rossumf6694362006-03-10 02:28:35 +0000588 def __exit__(self, t, v, tb): pass
Tim Peters400cbc32006-02-28 18:44:41 +0000589 targets = {1: [0, 1, 2]}
590 with C() as (targets[1][0], targets[1][1], targets[1][2]):
591 self.assertEqual(targets, {1: [1, 2, 3]})
592 with C() as (targets.values()[0][2], targets.values()[0][1], targets.values()[0][0]):
593 self.assertEqual(targets, {1: [3, 2, 1]})
594 with C() as (targets[1], targets[2], targets[3]):
595 self.assertEqual(targets, {1: 1, 2: 2, 3: 3})
596 class B: pass
597 blah = B()
598 with C() as (blah.one, blah.two, blah.three):
599 self.assertEqual(blah.one, 1)
600 self.assertEqual(blah.two, 2)
601 self.assertEqual(blah.three, 3)
602
603
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000604class ExitSwallowsExceptionTestCase(unittest.TestCase):
605
Guido van Rossumf6694362006-03-10 02:28:35 +0000606 def testExitTrueSwallowsException(self):
607 class AfricanSwallow:
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000608 def __enter__(self): pass
Guido van Rossumf6694362006-03-10 02:28:35 +0000609 def __exit__(self, t, v, tb): return True
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000610 try:
Guido van Rossumf6694362006-03-10 02:28:35 +0000611 with AfricanSwallow():
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000612 1/0
613 except ZeroDivisionError:
614 self.fail("ZeroDivisionError should have been swallowed")
615
Guido van Rossumf6694362006-03-10 02:28:35 +0000616 def testExitFalseDoesntSwallowException(self):
617 class EuropeanSwallow:
Guido van Rossumf6694362006-03-10 02:28:35 +0000618 def __enter__(self): pass
619 def __exit__(self, t, v, tb): return False
620 try:
621 with EuropeanSwallow():
622 1/0
623 except ZeroDivisionError:
624 pass
625 else:
626 self.fail("ZeroDivisionError should have been raised")
627
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000628
Benjamin Petersond1c7d072008-09-25 20:46:05 +0000629class NewKeywordsWarningTestCase(unittest.TestCase):
630
631 def check(self, code, word=None):
632 save = sys.stderr
633 sys.stderr = stream = StringIO.StringIO()
634 try:
635 compile(code, "<string>", "exec", 0, True)
636 finally:
637 sys.stderr = save
638 if word:
639 self.assert_("Warning: %r will become a reserved keyword in Python 2.6" % word
640 in stream.getvalue())
641 else:
642 self.assertEqual(stream.getvalue(), "")
643
644 def test_basic(self):
645 self.check("as = 4", "as")
646 self.check("with = 4", "with")
647 self.check("class as: pass", "as")
648 self.check("class with: pass", "with")
649 self.check("obj.as = 4", "as")
650 self.check("with.obj = 4", "with")
651 self.check("def with(): pass", "with")
652 self.check("do(); with = 23", "with")
653
654 def test_after_import(self):
655 # issue 3936
656 self.check("import sys\nas = 4", "as")
657 self.check("import sys\nwith = 4", "with")
658
659
Tim Peters400cbc32006-02-28 18:44:41 +0000660def test_main():
661 run_unittest(FailureTestCase, NonexceptionalTestCase,
662 NestedNonexceptionalTestCase, ExceptionalTestCase,
663 NonLocalFlowControlTestCase,
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000664 AssignmentTargetTestCase,
Benjamin Petersond1c7d072008-09-25 20:46:05 +0000665 ExitSwallowsExceptionTestCase,
666 NewKeywordsWarningTestCase)
Tim Peters400cbc32006-02-28 18:44:41 +0000667
668
669if __name__ == '__main__':
670 test_main()