ยปCore Development>Code coverage>Lib/test/test_with.py

Python code coverage for Lib/test/test_with.py

#countcontent
1n/a"""Unit tests for the with statement specified in PEP 343."""
2n/a
3n/a
4n/a__author__ = "Mike Bland"
5n/a__email__ = "mbland at acm dot org"
6n/a
7n/aimport sys
8n/aimport unittest
9n/afrom collections import deque
10n/afrom contextlib import _GeneratorContextManager, contextmanager
11n/a
12n/a
13n/aclass MockContextManager(_GeneratorContextManager):
14n/a def __init__(self, *args):
15n/a super().__init__(*args)
16n/a self.enter_called = False
17n/a self.exit_called = False
18n/a self.exit_args = None
19n/a
20n/a def __enter__(self):
21n/a self.enter_called = True
22n/a return _GeneratorContextManager.__enter__(self)
23n/a
24n/a def __exit__(self, type, value, traceback):
25n/a self.exit_called = True
26n/a self.exit_args = (type, value, traceback)
27n/a return _GeneratorContextManager.__exit__(self, type,
28n/a value, traceback)
29n/a
30n/a
31n/adef mock_contextmanager(func):
32n/a def helper(*args, **kwds):
33n/a return MockContextManager(func, args, kwds)
34n/a return helper
35n/a
36n/a
37n/aclass MockResource(object):
38n/a def __init__(self):
39n/a self.yielded = False
40n/a self.stopped = False
41n/a
42n/a
43n/a@mock_contextmanager
44n/adef mock_contextmanager_generator():
45n/a mock = MockResource()
46n/a try:
47n/a mock.yielded = True
48n/a yield mock
49n/a finally:
50n/a mock.stopped = True
51n/a
52n/a
53n/aclass Nested(object):
54n/a
55n/a def __init__(self, *managers):
56n/a self.managers = managers
57n/a self.entered = None
58n/a
59n/a def __enter__(self):
60n/a if self.entered is not None:
61n/a raise RuntimeError("Context is not reentrant")
62n/a self.entered = deque()
63n/a vars = []
64n/a try:
65n/a for mgr in self.managers:
66n/a vars.append(mgr.__enter__())
67n/a self.entered.appendleft(mgr)
68n/a except:
69n/a if not self.__exit__(*sys.exc_info()):
70n/a raise
71n/a return vars
72n/a
73n/a def __exit__(self, *exc_info):
74n/a # Behave like nested with statements
75n/a # first in, last out
76n/a # New exceptions override old ones
77n/a ex = exc_info
78n/a for mgr in self.entered:
79n/a try:
80n/a if mgr.__exit__(*ex):
81n/a ex = (None, None, None)
82n/a except:
83n/a ex = sys.exc_info()
84n/a self.entered = None
85n/a if ex is not exc_info:
86n/a raise ex[0](ex[1]).with_traceback(ex[2])
87n/a
88n/a
89n/aclass MockNested(Nested):
90n/a def __init__(self, *managers):
91n/a Nested.__init__(self, *managers)
92n/a self.enter_called = False
93n/a self.exit_called = False
94n/a self.exit_args = None
95n/a
96n/a def __enter__(self):
97n/a self.enter_called = True
98n/a return Nested.__enter__(self)
99n/a
100n/a def __exit__(self, *exc_info):
101n/a self.exit_called = True
102n/a self.exit_args = exc_info
103n/a return Nested.__exit__(self, *exc_info)
104n/a
105n/a
106n/aclass FailureTestCase(unittest.TestCase):
107n/a def testNameError(self):
108n/a def fooNotDeclared():
109n/a with foo: pass
110n/a self.assertRaises(NameError, fooNotDeclared)
111n/a
112n/a def testEnterAttributeError1(self):
113n/a class LacksEnter(object):
114n/a def __exit__(self, type, value, traceback):
115n/a pass
116n/a
117n/a def fooLacksEnter():
118n/a foo = LacksEnter()
119n/a with foo: pass
120n/a self.assertRaisesRegex(AttributeError, '__enter__', fooLacksEnter)
121n/a
122n/a def testEnterAttributeError2(self):
123n/a class LacksEnterAndExit(object):
124n/a pass
125n/a
126n/a def fooLacksEnterAndExit():
127n/a foo = LacksEnterAndExit()
128n/a with foo: pass
129n/a self.assertRaisesRegex(AttributeError, '__enter__', fooLacksEnterAndExit)
130n/a
131n/a def testExitAttributeError(self):
132n/a class LacksExit(object):
133n/a def __enter__(self):
134n/a pass
135n/a
136n/a def fooLacksExit():
137n/a foo = LacksExit()
138n/a with foo: pass
139n/a self.assertRaisesRegex(AttributeError, '__exit__', fooLacksExit)
140n/a
141n/a def assertRaisesSyntaxError(self, codestr):
142n/a def shouldRaiseSyntaxError(s):
143n/a compile(s, '', 'single')
144n/a self.assertRaises(SyntaxError, shouldRaiseSyntaxError, codestr)
145n/a
146n/a def testAssignmentToNoneError(self):
147n/a self.assertRaisesSyntaxError('with mock as None:\n pass')
148n/a self.assertRaisesSyntaxError(
149n/a 'with mock as (None):\n'
150n/a ' pass')
151n/a
152n/a def testAssignmentToTupleOnlyContainingNoneError(self):
153n/a self.assertRaisesSyntaxError('with mock as None,:\n pass')
154n/a self.assertRaisesSyntaxError(
155n/a 'with mock as (None,):\n'
156n/a ' pass')
157n/a
158n/a def testAssignmentToTupleContainingNoneError(self):
159n/a self.assertRaisesSyntaxError(
160n/a 'with mock as (foo, None, bar):\n'
161n/a ' pass')
162n/a
163n/a def testEnterThrows(self):
164n/a class EnterThrows(object):
165n/a def __enter__(self):
166n/a raise RuntimeError("Enter threw")
167n/a def __exit__(self, *args):
168n/a pass
169n/a
170n/a def shouldThrow():
171n/a ct = EnterThrows()
172n/a self.foo = None
173n/a with ct as self.foo:
174n/a pass
175n/a self.assertRaises(RuntimeError, shouldThrow)
176n/a self.assertEqual(self.foo, None)
177n/a
178n/a def testExitThrows(self):
179n/a class ExitThrows(object):
180n/a def __enter__(self):
181n/a return
182n/a def __exit__(self, *args):
183n/a raise RuntimeError(42)
184n/a def shouldThrow():
185n/a with ExitThrows():
186n/a pass
187n/a self.assertRaises(RuntimeError, shouldThrow)
188n/a
189n/aclass ContextmanagerAssertionMixin(object):
190n/a
191n/a def setUp(self):
192n/a self.TEST_EXCEPTION = RuntimeError("test exception")
193n/a
194n/a def assertInWithManagerInvariants(self, mock_manager):
195n/a self.assertTrue(mock_manager.enter_called)
196n/a self.assertFalse(mock_manager.exit_called)
197n/a self.assertEqual(mock_manager.exit_args, None)
198n/a
199n/a def assertAfterWithManagerInvariants(self, mock_manager, exit_args):
200n/a self.assertTrue(mock_manager.enter_called)
201n/a self.assertTrue(mock_manager.exit_called)
202n/a self.assertEqual(mock_manager.exit_args, exit_args)
203n/a
204n/a def assertAfterWithManagerInvariantsNoError(self, mock_manager):
205n/a self.assertAfterWithManagerInvariants(mock_manager,
206n/a (None, None, None))
207n/a
208n/a def assertInWithGeneratorInvariants(self, mock_generator):
209n/a self.assertTrue(mock_generator.yielded)
210n/a self.assertFalse(mock_generator.stopped)
211n/a
212n/a def assertAfterWithGeneratorInvariantsNoError(self, mock_generator):
213n/a self.assertTrue(mock_generator.yielded)
214n/a self.assertTrue(mock_generator.stopped)
215n/a
216n/a def raiseTestException(self):
217n/a raise self.TEST_EXCEPTION
218n/a
219n/a def assertAfterWithManagerInvariantsWithError(self, mock_manager,
220n/a exc_type=None):
221n/a self.assertTrue(mock_manager.enter_called)
222n/a self.assertTrue(mock_manager.exit_called)
223n/a if exc_type is None:
224n/a self.assertEqual(mock_manager.exit_args[1], self.TEST_EXCEPTION)
225n/a exc_type = type(self.TEST_EXCEPTION)
226n/a self.assertEqual(mock_manager.exit_args[0], exc_type)
227n/a # Test the __exit__ arguments. Issue #7853
228n/a self.assertIsInstance(mock_manager.exit_args[1], exc_type)
229n/a self.assertIsNot(mock_manager.exit_args[2], None)
230n/a
231n/a def assertAfterWithGeneratorInvariantsWithError(self, mock_generator):
232n/a self.assertTrue(mock_generator.yielded)
233n/a self.assertTrue(mock_generator.stopped)
234n/a
235n/a
236n/aclass NonexceptionalTestCase(unittest.TestCase, ContextmanagerAssertionMixin):
237n/a def testInlineGeneratorSyntax(self):
238n/a with mock_contextmanager_generator():
239n/a pass
240n/a
241n/a def testUnboundGenerator(self):
242n/a mock = mock_contextmanager_generator()
243n/a with mock:
244n/a pass
245n/a self.assertAfterWithManagerInvariantsNoError(mock)
246n/a
247n/a def testInlineGeneratorBoundSyntax(self):
248n/a with mock_contextmanager_generator() as foo:
249n/a self.assertInWithGeneratorInvariants(foo)
250n/a # FIXME: In the future, we'll try to keep the bound names from leaking
251n/a self.assertAfterWithGeneratorInvariantsNoError(foo)
252n/a
253n/a def testInlineGeneratorBoundToExistingVariable(self):
254n/a foo = None
255n/a with mock_contextmanager_generator() as foo:
256n/a self.assertInWithGeneratorInvariants(foo)
257n/a self.assertAfterWithGeneratorInvariantsNoError(foo)
258n/a
259n/a def testInlineGeneratorBoundToDottedVariable(self):
260n/a with mock_contextmanager_generator() as self.foo:
261n/a self.assertInWithGeneratorInvariants(self.foo)
262n/a self.assertAfterWithGeneratorInvariantsNoError(self.foo)
263n/a
264n/a def testBoundGenerator(self):
265n/a mock = mock_contextmanager_generator()
266n/a with mock as foo:
267n/a self.assertInWithGeneratorInvariants(foo)
268n/a self.assertInWithManagerInvariants(mock)
269n/a self.assertAfterWithGeneratorInvariantsNoError(foo)
270n/a self.assertAfterWithManagerInvariantsNoError(mock)
271n/a
272n/a def testNestedSingleStatements(self):
273n/a mock_a = mock_contextmanager_generator()
274n/a with mock_a as foo:
275n/a mock_b = mock_contextmanager_generator()
276n/a with mock_b as bar:
277n/a self.assertInWithManagerInvariants(mock_a)
278n/a self.assertInWithManagerInvariants(mock_b)
279n/a self.assertInWithGeneratorInvariants(foo)
280n/a self.assertInWithGeneratorInvariants(bar)
281n/a self.assertAfterWithManagerInvariantsNoError(mock_b)
282n/a self.assertAfterWithGeneratorInvariantsNoError(bar)
283n/a self.assertInWithManagerInvariants(mock_a)
284n/a self.assertInWithGeneratorInvariants(foo)
285n/a self.assertAfterWithManagerInvariantsNoError(mock_a)
286n/a self.assertAfterWithGeneratorInvariantsNoError(foo)
287n/a
288n/a
289n/aclass NestedNonexceptionalTestCase(unittest.TestCase,
290n/a ContextmanagerAssertionMixin):
291n/a def testSingleArgInlineGeneratorSyntax(self):
292n/a with Nested(mock_contextmanager_generator()):
293n/a pass
294n/a
295n/a def testSingleArgBoundToNonTuple(self):
296n/a m = mock_contextmanager_generator()
297n/a # This will bind all the arguments to nested() into a single list
298n/a # assigned to foo.
299n/a with Nested(m) as foo:
300n/a self.assertInWithManagerInvariants(m)
301n/a self.assertAfterWithManagerInvariantsNoError(m)
302n/a
303n/a def testSingleArgBoundToSingleElementParenthesizedList(self):
304n/a m = mock_contextmanager_generator()
305n/a # This will bind all the arguments to nested() into a single list
306n/a # assigned to foo.
307n/a with Nested(m) as (foo):
308n/a self.assertInWithManagerInvariants(m)
309n/a self.assertAfterWithManagerInvariantsNoError(m)
310n/a
311n/a def testSingleArgBoundToMultipleElementTupleError(self):
312n/a def shouldThrowValueError():
313n/a with Nested(mock_contextmanager_generator()) as (foo, bar):
314n/a pass
315n/a self.assertRaises(ValueError, shouldThrowValueError)
316n/a
317n/a def testSingleArgUnbound(self):
318n/a mock_contextmanager = mock_contextmanager_generator()
319n/a mock_nested = MockNested(mock_contextmanager)
320n/a with mock_nested:
321n/a self.assertInWithManagerInvariants(mock_contextmanager)
322n/a self.assertInWithManagerInvariants(mock_nested)
323n/a self.assertAfterWithManagerInvariantsNoError(mock_contextmanager)
324n/a self.assertAfterWithManagerInvariantsNoError(mock_nested)
325n/a
326n/a def testMultipleArgUnbound(self):
327n/a m = mock_contextmanager_generator()
328n/a n = mock_contextmanager_generator()
329n/a o = mock_contextmanager_generator()
330n/a mock_nested = MockNested(m, n, o)
331n/a with mock_nested:
332n/a self.assertInWithManagerInvariants(m)
333n/a self.assertInWithManagerInvariants(n)
334n/a self.assertInWithManagerInvariants(o)
335n/a self.assertInWithManagerInvariants(mock_nested)
336n/a self.assertAfterWithManagerInvariantsNoError(m)
337n/a self.assertAfterWithManagerInvariantsNoError(n)
338n/a self.assertAfterWithManagerInvariantsNoError(o)
339n/a self.assertAfterWithManagerInvariantsNoError(mock_nested)
340n/a
341n/a def testMultipleArgBound(self):
342n/a mock_nested = MockNested(mock_contextmanager_generator(),
343n/a mock_contextmanager_generator(), mock_contextmanager_generator())
344n/a with mock_nested as (m, n, o):
345n/a self.assertInWithGeneratorInvariants(m)
346n/a self.assertInWithGeneratorInvariants(n)
347n/a self.assertInWithGeneratorInvariants(o)
348n/a self.assertInWithManagerInvariants(mock_nested)
349n/a self.assertAfterWithGeneratorInvariantsNoError(m)
350n/a self.assertAfterWithGeneratorInvariantsNoError(n)
351n/a self.assertAfterWithGeneratorInvariantsNoError(o)
352n/a self.assertAfterWithManagerInvariantsNoError(mock_nested)
353n/a
354n/a
355n/aclass ExceptionalTestCase(ContextmanagerAssertionMixin, unittest.TestCase):
356n/a def testSingleResource(self):
357n/a cm = mock_contextmanager_generator()
358n/a def shouldThrow():
359n/a with cm as self.resource:
360n/a self.assertInWithManagerInvariants(cm)
361n/a self.assertInWithGeneratorInvariants(self.resource)
362n/a self.raiseTestException()
363n/a self.assertRaises(RuntimeError, shouldThrow)
364n/a self.assertAfterWithManagerInvariantsWithError(cm)
365n/a self.assertAfterWithGeneratorInvariantsWithError(self.resource)
366n/a
367n/a def testExceptionNormalized(self):
368n/a cm = mock_contextmanager_generator()
369n/a def shouldThrow():
370n/a with cm as self.resource:
371n/a # Note this relies on the fact that 1 // 0 produces an exception
372n/a # that is not normalized immediately.
373n/a 1 // 0
374n/a self.assertRaises(ZeroDivisionError, shouldThrow)
375n/a self.assertAfterWithManagerInvariantsWithError(cm, ZeroDivisionError)
376n/a
377n/a def testNestedSingleStatements(self):
378n/a mock_a = mock_contextmanager_generator()
379n/a mock_b = mock_contextmanager_generator()
380n/a def shouldThrow():
381n/a with mock_a as self.foo:
382n/a with mock_b as self.bar:
383n/a self.assertInWithManagerInvariants(mock_a)
384n/a self.assertInWithManagerInvariants(mock_b)
385n/a self.assertInWithGeneratorInvariants(self.foo)
386n/a self.assertInWithGeneratorInvariants(self.bar)
387n/a self.raiseTestException()
388n/a self.assertRaises(RuntimeError, shouldThrow)
389n/a self.assertAfterWithManagerInvariantsWithError(mock_a)
390n/a self.assertAfterWithManagerInvariantsWithError(mock_b)
391n/a self.assertAfterWithGeneratorInvariantsWithError(self.foo)
392n/a self.assertAfterWithGeneratorInvariantsWithError(self.bar)
393n/a
394n/a def testMultipleResourcesInSingleStatement(self):
395n/a cm_a = mock_contextmanager_generator()
396n/a cm_b = mock_contextmanager_generator()
397n/a mock_nested = MockNested(cm_a, cm_b)
398n/a def shouldThrow():
399n/a with mock_nested as (self.resource_a, self.resource_b):
400n/a self.assertInWithManagerInvariants(cm_a)
401n/a self.assertInWithManagerInvariants(cm_b)
402n/a self.assertInWithManagerInvariants(mock_nested)
403n/a self.assertInWithGeneratorInvariants(self.resource_a)
404n/a self.assertInWithGeneratorInvariants(self.resource_b)
405n/a self.raiseTestException()
406n/a self.assertRaises(RuntimeError, shouldThrow)
407n/a self.assertAfterWithManagerInvariantsWithError(cm_a)
408n/a self.assertAfterWithManagerInvariantsWithError(cm_b)
409n/a self.assertAfterWithManagerInvariantsWithError(mock_nested)
410n/a self.assertAfterWithGeneratorInvariantsWithError(self.resource_a)
411n/a self.assertAfterWithGeneratorInvariantsWithError(self.resource_b)
412n/a
413n/a def testNestedExceptionBeforeInnerStatement(self):
414n/a mock_a = mock_contextmanager_generator()
415n/a mock_b = mock_contextmanager_generator()
416n/a self.bar = None
417n/a def shouldThrow():
418n/a with mock_a as self.foo:
419n/a self.assertInWithManagerInvariants(mock_a)
420n/a self.assertInWithGeneratorInvariants(self.foo)
421n/a self.raiseTestException()
422n/a with mock_b as self.bar:
423n/a pass
424n/a self.assertRaises(RuntimeError, shouldThrow)
425n/a self.assertAfterWithManagerInvariantsWithError(mock_a)
426n/a self.assertAfterWithGeneratorInvariantsWithError(self.foo)
427n/a
428n/a # The inner statement stuff should never have been touched
429n/a self.assertEqual(self.bar, None)
430n/a self.assertFalse(mock_b.enter_called)
431n/a self.assertFalse(mock_b.exit_called)
432n/a self.assertEqual(mock_b.exit_args, None)
433n/a
434n/a def testNestedExceptionAfterInnerStatement(self):
435n/a mock_a = mock_contextmanager_generator()
436n/a mock_b = mock_contextmanager_generator()
437n/a def shouldThrow():
438n/a with mock_a as self.foo:
439n/a with mock_b as self.bar:
440n/a self.assertInWithManagerInvariants(mock_a)
441n/a self.assertInWithManagerInvariants(mock_b)
442n/a self.assertInWithGeneratorInvariants(self.foo)
443n/a self.assertInWithGeneratorInvariants(self.bar)
444n/a self.raiseTestException()
445n/a self.assertRaises(RuntimeError, shouldThrow)
446n/a self.assertAfterWithManagerInvariantsWithError(mock_a)
447n/a self.assertAfterWithManagerInvariantsNoError(mock_b)
448n/a self.assertAfterWithGeneratorInvariantsWithError(self.foo)
449n/a self.assertAfterWithGeneratorInvariantsNoError(self.bar)
450n/a
451n/a def testRaisedStopIteration1(self):
452n/a # From bug 1462485
453n/a @contextmanager
454n/a def cm():
455n/a yield
456n/a
457n/a def shouldThrow():
458n/a with cm():
459n/a raise StopIteration("from with")
460n/a
461n/a with self.assertWarnsRegex(DeprecationWarning, "StopIteration"):
462n/a self.assertRaises(StopIteration, shouldThrow)
463n/a
464n/a def testRaisedStopIteration2(self):
465n/a # From bug 1462485
466n/a class cm(object):
467n/a def __enter__(self):
468n/a pass
469n/a def __exit__(self, type, value, traceback):
470n/a pass
471n/a
472n/a def shouldThrow():
473n/a with cm():
474n/a raise StopIteration("from with")
475n/a
476n/a self.assertRaises(StopIteration, shouldThrow)
477n/a
478n/a def testRaisedStopIteration3(self):
479n/a # Another variant where the exception hasn't been instantiated
480n/a # From bug 1705170
481n/a @contextmanager
482n/a def cm():
483n/a yield
484n/a
485n/a def shouldThrow():
486n/a with cm():
487n/a raise next(iter([]))
488n/a
489n/a with self.assertWarnsRegex(DeprecationWarning, "StopIteration"):
490n/a self.assertRaises(StopIteration, shouldThrow)
491n/a
492n/a def testRaisedGeneratorExit1(self):
493n/a # From bug 1462485
494n/a @contextmanager
495n/a def cm():
496n/a yield
497n/a
498n/a def shouldThrow():
499n/a with cm():
500n/a raise GeneratorExit("from with")
501n/a
502n/a self.assertRaises(GeneratorExit, shouldThrow)
503n/a
504n/a def testRaisedGeneratorExit2(self):
505n/a # From bug 1462485
506n/a class cm (object):
507n/a def __enter__(self):
508n/a pass
509n/a def __exit__(self, type, value, traceback):
510n/a pass
511n/a
512n/a def shouldThrow():
513n/a with cm():
514n/a raise GeneratorExit("from with")
515n/a
516n/a self.assertRaises(GeneratorExit, shouldThrow)
517n/a
518n/a def testErrorsInBool(self):
519n/a # issue4589: __exit__ return code may raise an exception
520n/a # when looking at its truth value.
521n/a
522n/a class cm(object):
523n/a def __init__(self, bool_conversion):
524n/a class Bool:
525n/a def __bool__(self):
526n/a return bool_conversion()
527n/a self.exit_result = Bool()
528n/a def __enter__(self):
529n/a return 3
530n/a def __exit__(self, a, b, c):
531n/a return self.exit_result
532n/a
533n/a def trueAsBool():
534n/a with cm(lambda: True):
535n/a self.fail("Should NOT see this")
536n/a trueAsBool()
537n/a
538n/a def falseAsBool():
539n/a with cm(lambda: False):
540n/a self.fail("Should raise")
541n/a self.assertRaises(AssertionError, falseAsBool)
542n/a
543n/a def failAsBool():
544n/a with cm(lambda: 1//0):
545n/a self.fail("Should NOT see this")
546n/a self.assertRaises(ZeroDivisionError, failAsBool)
547n/a
548n/a
549n/aclass NonLocalFlowControlTestCase(unittest.TestCase):
550n/a
551n/a def testWithBreak(self):
552n/a counter = 0
553n/a while True:
554n/a counter += 1
555n/a with mock_contextmanager_generator():
556n/a counter += 10
557n/a break
558n/a counter += 100 # Not reached
559n/a self.assertEqual(counter, 11)
560n/a
561n/a def testWithContinue(self):
562n/a counter = 0
563n/a while True:
564n/a counter += 1
565n/a if counter > 2:
566n/a break
567n/a with mock_contextmanager_generator():
568n/a counter += 10
569n/a continue
570n/a counter += 100 # Not reached
571n/a self.assertEqual(counter, 12)
572n/a
573n/a def testWithReturn(self):
574n/a def foo():
575n/a counter = 0
576n/a while True:
577n/a counter += 1
578n/a with mock_contextmanager_generator():
579n/a counter += 10
580n/a return counter
581n/a counter += 100 # Not reached
582n/a self.assertEqual(foo(), 11)
583n/a
584n/a def testWithYield(self):
585n/a def gen():
586n/a with mock_contextmanager_generator():
587n/a yield 12
588n/a yield 13
589n/a x = list(gen())
590n/a self.assertEqual(x, [12, 13])
591n/a
592n/a def testWithRaise(self):
593n/a counter = 0
594n/a try:
595n/a counter += 1
596n/a with mock_contextmanager_generator():
597n/a counter += 10
598n/a raise RuntimeError
599n/a counter += 100 # Not reached
600n/a except RuntimeError:
601n/a self.assertEqual(counter, 11)
602n/a else:
603n/a self.fail("Didn't raise RuntimeError")
604n/a
605n/a
606n/aclass AssignmentTargetTestCase(unittest.TestCase):
607n/a
608n/a def testSingleComplexTarget(self):
609n/a targets = {1: [0, 1, 2]}
610n/a with mock_contextmanager_generator() as targets[1][0]:
611n/a self.assertEqual(list(targets.keys()), [1])
612n/a self.assertEqual(targets[1][0].__class__, MockResource)
613n/a with mock_contextmanager_generator() as list(targets.values())[0][1]:
614n/a self.assertEqual(list(targets.keys()), [1])
615n/a self.assertEqual(targets[1][1].__class__, MockResource)
616n/a with mock_contextmanager_generator() as targets[2]:
617n/a keys = list(targets.keys())
618n/a keys.sort()
619n/a self.assertEqual(keys, [1, 2])
620n/a class C: pass
621n/a blah = C()
622n/a with mock_contextmanager_generator() as blah.foo:
623n/a self.assertEqual(hasattr(blah, "foo"), True)
624n/a
625n/a def testMultipleComplexTargets(self):
626n/a class C:
627n/a def __enter__(self): return 1, 2, 3
628n/a def __exit__(self, t, v, tb): pass
629n/a targets = {1: [0, 1, 2]}
630n/a with C() as (targets[1][0], targets[1][1], targets[1][2]):
631n/a self.assertEqual(targets, {1: [1, 2, 3]})
632n/a with C() as (list(targets.values())[0][2], list(targets.values())[0][1], list(targets.values())[0][0]):
633n/a self.assertEqual(targets, {1: [3, 2, 1]})
634n/a with C() as (targets[1], targets[2], targets[3]):
635n/a self.assertEqual(targets, {1: 1, 2: 2, 3: 3})
636n/a class B: pass
637n/a blah = B()
638n/a with C() as (blah.one, blah.two, blah.three):
639n/a self.assertEqual(blah.one, 1)
640n/a self.assertEqual(blah.two, 2)
641n/a self.assertEqual(blah.three, 3)
642n/a
643n/a
644n/aclass ExitSwallowsExceptionTestCase(unittest.TestCase):
645n/a
646n/a def testExitTrueSwallowsException(self):
647n/a class AfricanSwallow:
648n/a def __enter__(self): pass
649n/a def __exit__(self, t, v, tb): return True
650n/a try:
651n/a with AfricanSwallow():
652n/a 1/0
653n/a except ZeroDivisionError:
654n/a self.fail("ZeroDivisionError should have been swallowed")
655n/a
656n/a def testExitFalseDoesntSwallowException(self):
657n/a class EuropeanSwallow:
658n/a def __enter__(self): pass
659n/a def __exit__(self, t, v, tb): return False
660n/a try:
661n/a with EuropeanSwallow():
662n/a 1/0
663n/a except ZeroDivisionError:
664n/a pass
665n/a else:
666n/a self.fail("ZeroDivisionError should have been raised")
667n/a
668n/a
669n/aclass NestedWith(unittest.TestCase):
670n/a
671n/a class Dummy(object):
672n/a def __init__(self, value=None, gobble=False):
673n/a if value is None:
674n/a value = self
675n/a self.value = value
676n/a self.gobble = gobble
677n/a self.enter_called = False
678n/a self.exit_called = False
679n/a
680n/a def __enter__(self):
681n/a self.enter_called = True
682n/a return self.value
683n/a
684n/a def __exit__(self, *exc_info):
685n/a self.exit_called = True
686n/a self.exc_info = exc_info
687n/a if self.gobble:
688n/a return True
689n/a
690n/a class InitRaises(object):
691n/a def __init__(self): raise RuntimeError()
692n/a
693n/a class EnterRaises(object):
694n/a def __enter__(self): raise RuntimeError()
695n/a def __exit__(self, *exc_info): pass
696n/a
697n/a class ExitRaises(object):
698n/a def __enter__(self): pass
699n/a def __exit__(self, *exc_info): raise RuntimeError()
700n/a
701n/a def testNoExceptions(self):
702n/a with self.Dummy() as a, self.Dummy() as b:
703n/a self.assertTrue(a.enter_called)
704n/a self.assertTrue(b.enter_called)
705n/a self.assertTrue(a.exit_called)
706n/a self.assertTrue(b.exit_called)
707n/a
708n/a def testExceptionInExprList(self):
709n/a try:
710n/a with self.Dummy() as a, self.InitRaises():
711n/a pass
712n/a except:
713n/a pass
714n/a self.assertTrue(a.enter_called)
715n/a self.assertTrue(a.exit_called)
716n/a
717n/a def testExceptionInEnter(self):
718n/a try:
719n/a with self.Dummy() as a, self.EnterRaises():
720n/a self.fail('body of bad with executed')
721n/a except RuntimeError:
722n/a pass
723n/a else:
724n/a self.fail('RuntimeError not reraised')
725n/a self.assertTrue(a.enter_called)
726n/a self.assertTrue(a.exit_called)
727n/a
728n/a def testExceptionInExit(self):
729n/a body_executed = False
730n/a with self.Dummy(gobble=True) as a, self.ExitRaises():
731n/a body_executed = True
732n/a self.assertTrue(a.enter_called)
733n/a self.assertTrue(a.exit_called)
734n/a self.assertTrue(body_executed)
735n/a self.assertNotEqual(a.exc_info[0], None)
736n/a
737n/a def testEnterReturnsTuple(self):
738n/a with self.Dummy(value=(1,2)) as (a1, a2), \
739n/a self.Dummy(value=(10, 20)) as (b1, b2):
740n/a self.assertEqual(1, a1)
741n/a self.assertEqual(2, a2)
742n/a self.assertEqual(10, b1)
743n/a self.assertEqual(20, b2)
744n/a
745n/aif __name__ == '__main__':
746n/a unittest.main()