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

Python code coverage for Lib/test/test_yield_from.py

#countcontent
1n/a# -*- coding: utf-8 -*-
2n/a
3n/a"""
4n/aTest suite for PEP 380 implementation
5n/a
6n/aadapted from original tests written by Greg Ewing
7n/asee <http://www.cosc.canterbury.ac.nz/greg.ewing/python/yield-from/YieldFrom-Python3.1.2-rev5.zip>
8n/a"""
9n/a
10n/aimport unittest
11n/aimport inspect
12n/a
13n/afrom test.support import captured_stderr, disable_gc, gc_collect
14n/a
15n/aclass TestPEP380Operation(unittest.TestCase):
16n/a """
17n/a Test semantics.
18n/a """
19n/a
20n/a def test_delegation_of_initial_next_to_subgenerator(self):
21n/a """
22n/a Test delegation of initial next() call to subgenerator
23n/a """
24n/a trace = []
25n/a def g1():
26n/a trace.append("Starting g1")
27n/a yield from g2()
28n/a trace.append("Finishing g1")
29n/a def g2():
30n/a trace.append("Starting g2")
31n/a yield 42
32n/a trace.append("Finishing g2")
33n/a for x in g1():
34n/a trace.append("Yielded %s" % (x,))
35n/a self.assertEqual(trace,[
36n/a "Starting g1",
37n/a "Starting g2",
38n/a "Yielded 42",
39n/a "Finishing g2",
40n/a "Finishing g1",
41n/a ])
42n/a
43n/a def test_raising_exception_in_initial_next_call(self):
44n/a """
45n/a Test raising exception in initial next() call
46n/a """
47n/a trace = []
48n/a def g1():
49n/a try:
50n/a trace.append("Starting g1")
51n/a yield from g2()
52n/a finally:
53n/a trace.append("Finishing g1")
54n/a def g2():
55n/a try:
56n/a trace.append("Starting g2")
57n/a raise ValueError("spanish inquisition occurred")
58n/a finally:
59n/a trace.append("Finishing g2")
60n/a try:
61n/a for x in g1():
62n/a trace.append("Yielded %s" % (x,))
63n/a except ValueError as e:
64n/a self.assertEqual(e.args[0], "spanish inquisition occurred")
65n/a else:
66n/a self.fail("subgenerator failed to raise ValueError")
67n/a self.assertEqual(trace,[
68n/a "Starting g1",
69n/a "Starting g2",
70n/a "Finishing g2",
71n/a "Finishing g1",
72n/a ])
73n/a
74n/a def test_delegation_of_next_call_to_subgenerator(self):
75n/a """
76n/a Test delegation of next() call to subgenerator
77n/a """
78n/a trace = []
79n/a def g1():
80n/a trace.append("Starting g1")
81n/a yield "g1 ham"
82n/a yield from g2()
83n/a yield "g1 eggs"
84n/a trace.append("Finishing g1")
85n/a def g2():
86n/a trace.append("Starting g2")
87n/a yield "g2 spam"
88n/a yield "g2 more spam"
89n/a trace.append("Finishing g2")
90n/a for x in g1():
91n/a trace.append("Yielded %s" % (x,))
92n/a self.assertEqual(trace,[
93n/a "Starting g1",
94n/a "Yielded g1 ham",
95n/a "Starting g2",
96n/a "Yielded g2 spam",
97n/a "Yielded g2 more spam",
98n/a "Finishing g2",
99n/a "Yielded g1 eggs",
100n/a "Finishing g1",
101n/a ])
102n/a
103n/a def test_raising_exception_in_delegated_next_call(self):
104n/a """
105n/a Test raising exception in delegated next() call
106n/a """
107n/a trace = []
108n/a def g1():
109n/a try:
110n/a trace.append("Starting g1")
111n/a yield "g1 ham"
112n/a yield from g2()
113n/a yield "g1 eggs"
114n/a finally:
115n/a trace.append("Finishing g1")
116n/a def g2():
117n/a try:
118n/a trace.append("Starting g2")
119n/a yield "g2 spam"
120n/a raise ValueError("hovercraft is full of eels")
121n/a yield "g2 more spam"
122n/a finally:
123n/a trace.append("Finishing g2")
124n/a try:
125n/a for x in g1():
126n/a trace.append("Yielded %s" % (x,))
127n/a except ValueError as e:
128n/a self.assertEqual(e.args[0], "hovercraft is full of eels")
129n/a else:
130n/a self.fail("subgenerator failed to raise ValueError")
131n/a self.assertEqual(trace,[
132n/a "Starting g1",
133n/a "Yielded g1 ham",
134n/a "Starting g2",
135n/a "Yielded g2 spam",
136n/a "Finishing g2",
137n/a "Finishing g1",
138n/a ])
139n/a
140n/a def test_delegation_of_send(self):
141n/a """
142n/a Test delegation of send()
143n/a """
144n/a trace = []
145n/a def g1():
146n/a trace.append("Starting g1")
147n/a x = yield "g1 ham"
148n/a trace.append("g1 received %s" % (x,))
149n/a yield from g2()
150n/a x = yield "g1 eggs"
151n/a trace.append("g1 received %s" % (x,))
152n/a trace.append("Finishing g1")
153n/a def g2():
154n/a trace.append("Starting g2")
155n/a x = yield "g2 spam"
156n/a trace.append("g2 received %s" % (x,))
157n/a x = yield "g2 more spam"
158n/a trace.append("g2 received %s" % (x,))
159n/a trace.append("Finishing g2")
160n/a g = g1()
161n/a y = next(g)
162n/a x = 1
163n/a try:
164n/a while 1:
165n/a y = g.send(x)
166n/a trace.append("Yielded %s" % (y,))
167n/a x += 1
168n/a except StopIteration:
169n/a pass
170n/a self.assertEqual(trace,[
171n/a "Starting g1",
172n/a "g1 received 1",
173n/a "Starting g2",
174n/a "Yielded g2 spam",
175n/a "g2 received 2",
176n/a "Yielded g2 more spam",
177n/a "g2 received 3",
178n/a "Finishing g2",
179n/a "Yielded g1 eggs",
180n/a "g1 received 4",
181n/a "Finishing g1",
182n/a ])
183n/a
184n/a def test_handling_exception_while_delegating_send(self):
185n/a """
186n/a Test handling exception while delegating 'send'
187n/a """
188n/a trace = []
189n/a def g1():
190n/a trace.append("Starting g1")
191n/a x = yield "g1 ham"
192n/a trace.append("g1 received %s" % (x,))
193n/a yield from g2()
194n/a x = yield "g1 eggs"
195n/a trace.append("g1 received %s" % (x,))
196n/a trace.append("Finishing g1")
197n/a def g2():
198n/a trace.append("Starting g2")
199n/a x = yield "g2 spam"
200n/a trace.append("g2 received %s" % (x,))
201n/a raise ValueError("hovercraft is full of eels")
202n/a x = yield "g2 more spam"
203n/a trace.append("g2 received %s" % (x,))
204n/a trace.append("Finishing g2")
205n/a def run():
206n/a g = g1()
207n/a y = next(g)
208n/a x = 1
209n/a try:
210n/a while 1:
211n/a y = g.send(x)
212n/a trace.append("Yielded %s" % (y,))
213n/a x += 1
214n/a except StopIteration:
215n/a trace.append("StopIteration")
216n/a self.assertRaises(ValueError,run)
217n/a self.assertEqual(trace,[
218n/a "Starting g1",
219n/a "g1 received 1",
220n/a "Starting g2",
221n/a "Yielded g2 spam",
222n/a "g2 received 2",
223n/a ])
224n/a
225n/a def test_delegating_close(self):
226n/a """
227n/a Test delegating 'close'
228n/a """
229n/a trace = []
230n/a def g1():
231n/a try:
232n/a trace.append("Starting g1")
233n/a yield "g1 ham"
234n/a yield from g2()
235n/a yield "g1 eggs"
236n/a finally:
237n/a trace.append("Finishing g1")
238n/a def g2():
239n/a try:
240n/a trace.append("Starting g2")
241n/a yield "g2 spam"
242n/a yield "g2 more spam"
243n/a finally:
244n/a trace.append("Finishing g2")
245n/a g = g1()
246n/a for i in range(2):
247n/a x = next(g)
248n/a trace.append("Yielded %s" % (x,))
249n/a g.close()
250n/a self.assertEqual(trace,[
251n/a "Starting g1",
252n/a "Yielded g1 ham",
253n/a "Starting g2",
254n/a "Yielded g2 spam",
255n/a "Finishing g2",
256n/a "Finishing g1"
257n/a ])
258n/a
259n/a def test_handing_exception_while_delegating_close(self):
260n/a """
261n/a Test handling exception while delegating 'close'
262n/a """
263n/a trace = []
264n/a def g1():
265n/a try:
266n/a trace.append("Starting g1")
267n/a yield "g1 ham"
268n/a yield from g2()
269n/a yield "g1 eggs"
270n/a finally:
271n/a trace.append("Finishing g1")
272n/a def g2():
273n/a try:
274n/a trace.append("Starting g2")
275n/a yield "g2 spam"
276n/a yield "g2 more spam"
277n/a finally:
278n/a trace.append("Finishing g2")
279n/a raise ValueError("nybbles have exploded with delight")
280n/a try:
281n/a g = g1()
282n/a for i in range(2):
283n/a x = next(g)
284n/a trace.append("Yielded %s" % (x,))
285n/a g.close()
286n/a except ValueError as e:
287n/a self.assertEqual(e.args[0], "nybbles have exploded with delight")
288n/a self.assertIsInstance(e.__context__, GeneratorExit)
289n/a else:
290n/a self.fail("subgenerator failed to raise ValueError")
291n/a self.assertEqual(trace,[
292n/a "Starting g1",
293n/a "Yielded g1 ham",
294n/a "Starting g2",
295n/a "Yielded g2 spam",
296n/a "Finishing g2",
297n/a "Finishing g1",
298n/a ])
299n/a
300n/a def test_delegating_throw(self):
301n/a """
302n/a Test delegating 'throw'
303n/a """
304n/a trace = []
305n/a def g1():
306n/a try:
307n/a trace.append("Starting g1")
308n/a yield "g1 ham"
309n/a yield from g2()
310n/a yield "g1 eggs"
311n/a finally:
312n/a trace.append("Finishing g1")
313n/a def g2():
314n/a try:
315n/a trace.append("Starting g2")
316n/a yield "g2 spam"
317n/a yield "g2 more spam"
318n/a finally:
319n/a trace.append("Finishing g2")
320n/a try:
321n/a g = g1()
322n/a for i in range(2):
323n/a x = next(g)
324n/a trace.append("Yielded %s" % (x,))
325n/a e = ValueError("tomato ejected")
326n/a g.throw(e)
327n/a except ValueError as e:
328n/a self.assertEqual(e.args[0], "tomato ejected")
329n/a else:
330n/a self.fail("subgenerator failed to raise ValueError")
331n/a self.assertEqual(trace,[
332n/a "Starting g1",
333n/a "Yielded g1 ham",
334n/a "Starting g2",
335n/a "Yielded g2 spam",
336n/a "Finishing g2",
337n/a "Finishing g1",
338n/a ])
339n/a
340n/a def test_value_attribute_of_StopIteration_exception(self):
341n/a """
342n/a Test 'value' attribute of StopIteration exception
343n/a """
344n/a trace = []
345n/a def pex(e):
346n/a trace.append("%s: %s" % (e.__class__.__name__, e))
347n/a trace.append("value = %s" % (e.value,))
348n/a e = StopIteration()
349n/a pex(e)
350n/a e = StopIteration("spam")
351n/a pex(e)
352n/a e.value = "eggs"
353n/a pex(e)
354n/a self.assertEqual(trace,[
355n/a "StopIteration: ",
356n/a "value = None",
357n/a "StopIteration: spam",
358n/a "value = spam",
359n/a "StopIteration: spam",
360n/a "value = eggs",
361n/a ])
362n/a
363n/a
364n/a def test_exception_value_crash(self):
365n/a # There used to be a refcount error when the return value
366n/a # stored in the StopIteration has a refcount of 1.
367n/a def g1():
368n/a yield from g2()
369n/a def g2():
370n/a yield "g2"
371n/a return [42]
372n/a self.assertEqual(list(g1()), ["g2"])
373n/a
374n/a
375n/a def test_generator_return_value(self):
376n/a """
377n/a Test generator return value
378n/a """
379n/a trace = []
380n/a def g1():
381n/a trace.append("Starting g1")
382n/a yield "g1 ham"
383n/a ret = yield from g2()
384n/a trace.append("g2 returned %r" % (ret,))
385n/a for v in 1, (2,), StopIteration(3):
386n/a ret = yield from g2(v)
387n/a trace.append("g2 returned %r" % (ret,))
388n/a yield "g1 eggs"
389n/a trace.append("Finishing g1")
390n/a def g2(v = None):
391n/a trace.append("Starting g2")
392n/a yield "g2 spam"
393n/a yield "g2 more spam"
394n/a trace.append("Finishing g2")
395n/a if v:
396n/a return v
397n/a for x in g1():
398n/a trace.append("Yielded %s" % (x,))
399n/a self.assertEqual(trace,[
400n/a "Starting g1",
401n/a "Yielded g1 ham",
402n/a "Starting g2",
403n/a "Yielded g2 spam",
404n/a "Yielded g2 more spam",
405n/a "Finishing g2",
406n/a "g2 returned None",
407n/a "Starting g2",
408n/a "Yielded g2 spam",
409n/a "Yielded g2 more spam",
410n/a "Finishing g2",
411n/a "g2 returned 1",
412n/a "Starting g2",
413n/a "Yielded g2 spam",
414n/a "Yielded g2 more spam",
415n/a "Finishing g2",
416n/a "g2 returned (2,)",
417n/a "Starting g2",
418n/a "Yielded g2 spam",
419n/a "Yielded g2 more spam",
420n/a "Finishing g2",
421n/a "g2 returned StopIteration(3,)",
422n/a "Yielded g1 eggs",
423n/a "Finishing g1",
424n/a ])
425n/a
426n/a def test_delegation_of_next_to_non_generator(self):
427n/a """
428n/a Test delegation of next() to non-generator
429n/a """
430n/a trace = []
431n/a def g():
432n/a yield from range(3)
433n/a for x in g():
434n/a trace.append("Yielded %s" % (x,))
435n/a self.assertEqual(trace,[
436n/a "Yielded 0",
437n/a "Yielded 1",
438n/a "Yielded 2",
439n/a ])
440n/a
441n/a
442n/a def test_conversion_of_sendNone_to_next(self):
443n/a """
444n/a Test conversion of send(None) to next()
445n/a """
446n/a trace = []
447n/a def g():
448n/a yield from range(3)
449n/a gi = g()
450n/a for x in range(3):
451n/a y = gi.send(None)
452n/a trace.append("Yielded: %s" % (y,))
453n/a self.assertEqual(trace,[
454n/a "Yielded: 0",
455n/a "Yielded: 1",
456n/a "Yielded: 2",
457n/a ])
458n/a
459n/a def test_delegation_of_close_to_non_generator(self):
460n/a """
461n/a Test delegation of close() to non-generator
462n/a """
463n/a trace = []
464n/a def g():
465n/a try:
466n/a trace.append("starting g")
467n/a yield from range(3)
468n/a trace.append("g should not be here")
469n/a finally:
470n/a trace.append("finishing g")
471n/a gi = g()
472n/a next(gi)
473n/a with captured_stderr() as output:
474n/a gi.close()
475n/a self.assertEqual(output.getvalue(), '')
476n/a self.assertEqual(trace,[
477n/a "starting g",
478n/a "finishing g",
479n/a ])
480n/a
481n/a def test_delegating_throw_to_non_generator(self):
482n/a """
483n/a Test delegating 'throw' to non-generator
484n/a """
485n/a trace = []
486n/a def g():
487n/a try:
488n/a trace.append("Starting g")
489n/a yield from range(10)
490n/a finally:
491n/a trace.append("Finishing g")
492n/a try:
493n/a gi = g()
494n/a for i in range(5):
495n/a x = next(gi)
496n/a trace.append("Yielded %s" % (x,))
497n/a e = ValueError("tomato ejected")
498n/a gi.throw(e)
499n/a except ValueError as e:
500n/a self.assertEqual(e.args[0],"tomato ejected")
501n/a else:
502n/a self.fail("subgenerator failed to raise ValueError")
503n/a self.assertEqual(trace,[
504n/a "Starting g",
505n/a "Yielded 0",
506n/a "Yielded 1",
507n/a "Yielded 2",
508n/a "Yielded 3",
509n/a "Yielded 4",
510n/a "Finishing g",
511n/a ])
512n/a
513n/a def test_attempting_to_send_to_non_generator(self):
514n/a """
515n/a Test attempting to send to non-generator
516n/a """
517n/a trace = []
518n/a def g():
519n/a try:
520n/a trace.append("starting g")
521n/a yield from range(3)
522n/a trace.append("g should not be here")
523n/a finally:
524n/a trace.append("finishing g")
525n/a try:
526n/a gi = g()
527n/a next(gi)
528n/a for x in range(3):
529n/a y = gi.send(42)
530n/a trace.append("Should not have yielded: %s" % (y,))
531n/a except AttributeError as e:
532n/a self.assertIn("send", e.args[0])
533n/a else:
534n/a self.fail("was able to send into non-generator")
535n/a self.assertEqual(trace,[
536n/a "starting g",
537n/a "finishing g",
538n/a ])
539n/a
540n/a def test_broken_getattr_handling(self):
541n/a """
542n/a Test subiterator with a broken getattr implementation
543n/a """
544n/a class Broken:
545n/a def __iter__(self):
546n/a return self
547n/a def __next__(self):
548n/a return 1
549n/a def __getattr__(self, attr):
550n/a 1/0
551n/a
552n/a def g():
553n/a yield from Broken()
554n/a
555n/a with self.assertRaises(ZeroDivisionError):
556n/a gi = g()
557n/a self.assertEqual(next(gi), 1)
558n/a gi.send(1)
559n/a
560n/a with self.assertRaises(ZeroDivisionError):
561n/a gi = g()
562n/a self.assertEqual(next(gi), 1)
563n/a gi.throw(AttributeError)
564n/a
565n/a with captured_stderr() as output:
566n/a gi = g()
567n/a self.assertEqual(next(gi), 1)
568n/a gi.close()
569n/a self.assertIn('ZeroDivisionError', output.getvalue())
570n/a
571n/a def test_exception_in_initial_next_call(self):
572n/a """
573n/a Test exception in initial next() call
574n/a """
575n/a trace = []
576n/a def g1():
577n/a trace.append("g1 about to yield from g2")
578n/a yield from g2()
579n/a trace.append("g1 should not be here")
580n/a def g2():
581n/a yield 1/0
582n/a def run():
583n/a gi = g1()
584n/a next(gi)
585n/a self.assertRaises(ZeroDivisionError,run)
586n/a self.assertEqual(trace,[
587n/a "g1 about to yield from g2"
588n/a ])
589n/a
590n/a def test_attempted_yield_from_loop(self):
591n/a """
592n/a Test attempted yield-from loop
593n/a """
594n/a trace = []
595n/a def g1():
596n/a trace.append("g1: starting")
597n/a yield "y1"
598n/a trace.append("g1: about to yield from g2")
599n/a yield from g2()
600n/a trace.append("g1 should not be here")
601n/a
602n/a def g2():
603n/a trace.append("g2: starting")
604n/a yield "y2"
605n/a trace.append("g2: about to yield from g1")
606n/a yield from gi
607n/a trace.append("g2 should not be here")
608n/a try:
609n/a gi = g1()
610n/a for y in gi:
611n/a trace.append("Yielded: %s" % (y,))
612n/a except ValueError as e:
613n/a self.assertEqual(e.args[0],"generator already executing")
614n/a else:
615n/a self.fail("subgenerator didn't raise ValueError")
616n/a self.assertEqual(trace,[
617n/a "g1: starting",
618n/a "Yielded: y1",
619n/a "g1: about to yield from g2",
620n/a "g2: starting",
621n/a "Yielded: y2",
622n/a "g2: about to yield from g1",
623n/a ])
624n/a
625n/a def test_returning_value_from_delegated_throw(self):
626n/a """
627n/a Test returning value from delegated 'throw'
628n/a """
629n/a trace = []
630n/a def g1():
631n/a try:
632n/a trace.append("Starting g1")
633n/a yield "g1 ham"
634n/a yield from g2()
635n/a yield "g1 eggs"
636n/a finally:
637n/a trace.append("Finishing g1")
638n/a def g2():
639n/a try:
640n/a trace.append("Starting g2")
641n/a yield "g2 spam"
642n/a yield "g2 more spam"
643n/a except LunchError:
644n/a trace.append("Caught LunchError in g2")
645n/a yield "g2 lunch saved"
646n/a yield "g2 yet more spam"
647n/a class LunchError(Exception):
648n/a pass
649n/a g = g1()
650n/a for i in range(2):
651n/a x = next(g)
652n/a trace.append("Yielded %s" % (x,))
653n/a e = LunchError("tomato ejected")
654n/a g.throw(e)
655n/a for x in g:
656n/a trace.append("Yielded %s" % (x,))
657n/a self.assertEqual(trace,[
658n/a "Starting g1",
659n/a "Yielded g1 ham",
660n/a "Starting g2",
661n/a "Yielded g2 spam",
662n/a "Caught LunchError in g2",
663n/a "Yielded g2 yet more spam",
664n/a "Yielded g1 eggs",
665n/a "Finishing g1",
666n/a ])
667n/a
668n/a def test_next_and_return_with_value(self):
669n/a """
670n/a Test next and return with value
671n/a """
672n/a trace = []
673n/a def f(r):
674n/a gi = g(r)
675n/a next(gi)
676n/a try:
677n/a trace.append("f resuming g")
678n/a next(gi)
679n/a trace.append("f SHOULD NOT BE HERE")
680n/a except StopIteration as e:
681n/a trace.append("f caught %r" % (e,))
682n/a def g(r):
683n/a trace.append("g starting")
684n/a yield
685n/a trace.append("g returning %r" % (r,))
686n/a return r
687n/a f(None)
688n/a f(1)
689n/a f((2,))
690n/a f(StopIteration(3))
691n/a self.assertEqual(trace,[
692n/a "g starting",
693n/a "f resuming g",
694n/a "g returning None",
695n/a "f caught StopIteration()",
696n/a "g starting",
697n/a "f resuming g",
698n/a "g returning 1",
699n/a "f caught StopIteration(1,)",
700n/a "g starting",
701n/a "f resuming g",
702n/a "g returning (2,)",
703n/a "f caught StopIteration((2,),)",
704n/a "g starting",
705n/a "f resuming g",
706n/a "g returning StopIteration(3,)",
707n/a "f caught StopIteration(StopIteration(3,),)",
708n/a ])
709n/a
710n/a def test_send_and_return_with_value(self):
711n/a """
712n/a Test send and return with value
713n/a """
714n/a trace = []
715n/a def f(r):
716n/a gi = g(r)
717n/a next(gi)
718n/a try:
719n/a trace.append("f sending spam to g")
720n/a gi.send("spam")
721n/a trace.append("f SHOULD NOT BE HERE")
722n/a except StopIteration as e:
723n/a trace.append("f caught %r" % (e,))
724n/a def g(r):
725n/a trace.append("g starting")
726n/a x = yield
727n/a trace.append("g received %r" % (x,))
728n/a trace.append("g returning %r" % (r,))
729n/a return r
730n/a f(None)
731n/a f(1)
732n/a f((2,))
733n/a f(StopIteration(3))
734n/a self.assertEqual(trace, [
735n/a "g starting",
736n/a "f sending spam to g",
737n/a "g received 'spam'",
738n/a "g returning None",
739n/a "f caught StopIteration()",
740n/a "g starting",
741n/a "f sending spam to g",
742n/a "g received 'spam'",
743n/a "g returning 1",
744n/a 'f caught StopIteration(1,)',
745n/a 'g starting',
746n/a 'f sending spam to g',
747n/a "g received 'spam'",
748n/a 'g returning (2,)',
749n/a 'f caught StopIteration((2,),)',
750n/a 'g starting',
751n/a 'f sending spam to g',
752n/a "g received 'spam'",
753n/a 'g returning StopIteration(3,)',
754n/a 'f caught StopIteration(StopIteration(3,),)'
755n/a ])
756n/a
757n/a def test_catching_exception_from_subgen_and_returning(self):
758n/a """
759n/a Test catching an exception thrown into a
760n/a subgenerator and returning a value
761n/a """
762n/a def inner():
763n/a try:
764n/a yield 1
765n/a except ValueError:
766n/a trace.append("inner caught ValueError")
767n/a return value
768n/a
769n/a def outer():
770n/a v = yield from inner()
771n/a trace.append("inner returned %r to outer" % (v,))
772n/a yield v
773n/a
774n/a for value in 2, (2,), StopIteration(2):
775n/a trace = []
776n/a g = outer()
777n/a trace.append(next(g))
778n/a trace.append(repr(g.throw(ValueError)))
779n/a self.assertEqual(trace, [
780n/a 1,
781n/a "inner caught ValueError",
782n/a "inner returned %r to outer" % (value,),
783n/a repr(value),
784n/a ])
785n/a
786n/a def test_throwing_GeneratorExit_into_subgen_that_returns(self):
787n/a """
788n/a Test throwing GeneratorExit into a subgenerator that
789n/a catches it and returns normally.
790n/a """
791n/a trace = []
792n/a def f():
793n/a try:
794n/a trace.append("Enter f")
795n/a yield
796n/a trace.append("Exit f")
797n/a except GeneratorExit:
798n/a return
799n/a def g():
800n/a trace.append("Enter g")
801n/a yield from f()
802n/a trace.append("Exit g")
803n/a try:
804n/a gi = g()
805n/a next(gi)
806n/a gi.throw(GeneratorExit)
807n/a except GeneratorExit:
808n/a pass
809n/a else:
810n/a self.fail("subgenerator failed to raise GeneratorExit")
811n/a self.assertEqual(trace,[
812n/a "Enter g",
813n/a "Enter f",
814n/a ])
815n/a
816n/a def test_throwing_GeneratorExit_into_subgenerator_that_yields(self):
817n/a """
818n/a Test throwing GeneratorExit into a subgenerator that
819n/a catches it and yields.
820n/a """
821n/a trace = []
822n/a def f():
823n/a try:
824n/a trace.append("Enter f")
825n/a yield
826n/a trace.append("Exit f")
827n/a except GeneratorExit:
828n/a yield
829n/a def g():
830n/a trace.append("Enter g")
831n/a yield from f()
832n/a trace.append("Exit g")
833n/a try:
834n/a gi = g()
835n/a next(gi)
836n/a gi.throw(GeneratorExit)
837n/a except RuntimeError as e:
838n/a self.assertEqual(e.args[0], "generator ignored GeneratorExit")
839n/a else:
840n/a self.fail("subgenerator failed to raise GeneratorExit")
841n/a self.assertEqual(trace,[
842n/a "Enter g",
843n/a "Enter f",
844n/a ])
845n/a
846n/a def test_throwing_GeneratorExit_into_subgen_that_raises(self):
847n/a """
848n/a Test throwing GeneratorExit into a subgenerator that
849n/a catches it and raises a different exception.
850n/a """
851n/a trace = []
852n/a def f():
853n/a try:
854n/a trace.append("Enter f")
855n/a yield
856n/a trace.append("Exit f")
857n/a except GeneratorExit:
858n/a raise ValueError("Vorpal bunny encountered")
859n/a def g():
860n/a trace.append("Enter g")
861n/a yield from f()
862n/a trace.append("Exit g")
863n/a try:
864n/a gi = g()
865n/a next(gi)
866n/a gi.throw(GeneratorExit)
867n/a except ValueError as e:
868n/a self.assertEqual(e.args[0], "Vorpal bunny encountered")
869n/a self.assertIsInstance(e.__context__, GeneratorExit)
870n/a else:
871n/a self.fail("subgenerator failed to raise ValueError")
872n/a self.assertEqual(trace,[
873n/a "Enter g",
874n/a "Enter f",
875n/a ])
876n/a
877n/a def test_yield_from_empty(self):
878n/a def g():
879n/a yield from ()
880n/a self.assertRaises(StopIteration, next, g())
881n/a
882n/a def test_delegating_generators_claim_to_be_running(self):
883n/a # Check with basic iteration
884n/a def one():
885n/a yield 0
886n/a yield from two()
887n/a yield 3
888n/a def two():
889n/a yield 1
890n/a try:
891n/a yield from g1
892n/a except ValueError:
893n/a pass
894n/a yield 2
895n/a g1 = one()
896n/a self.assertEqual(list(g1), [0, 1, 2, 3])
897n/a # Check with send
898n/a g1 = one()
899n/a res = [next(g1)]
900n/a try:
901n/a while True:
902n/a res.append(g1.send(42))
903n/a except StopIteration:
904n/a pass
905n/a self.assertEqual(res, [0, 1, 2, 3])
906n/a # Check with throw
907n/a class MyErr(Exception):
908n/a pass
909n/a def one():
910n/a try:
911n/a yield 0
912n/a except MyErr:
913n/a pass
914n/a yield from two()
915n/a try:
916n/a yield 3
917n/a except MyErr:
918n/a pass
919n/a def two():
920n/a try:
921n/a yield 1
922n/a except MyErr:
923n/a pass
924n/a try:
925n/a yield from g1
926n/a except ValueError:
927n/a pass
928n/a try:
929n/a yield 2
930n/a except MyErr:
931n/a pass
932n/a g1 = one()
933n/a res = [next(g1)]
934n/a try:
935n/a while True:
936n/a res.append(g1.throw(MyErr))
937n/a except StopIteration:
938n/a pass
939n/a # Check with close
940n/a class MyIt(object):
941n/a def __iter__(self):
942n/a return self
943n/a def __next__(self):
944n/a return 42
945n/a def close(self_):
946n/a self.assertTrue(g1.gi_running)
947n/a self.assertRaises(ValueError, next, g1)
948n/a def one():
949n/a yield from MyIt()
950n/a g1 = one()
951n/a next(g1)
952n/a g1.close()
953n/a
954n/a def test_delegator_is_visible_to_debugger(self):
955n/a def call_stack():
956n/a return [f[3] for f in inspect.stack()]
957n/a
958n/a def gen():
959n/a yield call_stack()
960n/a yield call_stack()
961n/a yield call_stack()
962n/a
963n/a def spam(g):
964n/a yield from g
965n/a
966n/a def eggs(g):
967n/a yield from g
968n/a
969n/a for stack in spam(gen()):
970n/a self.assertTrue('spam' in stack)
971n/a
972n/a for stack in spam(eggs(gen())):
973n/a self.assertTrue('spam' in stack and 'eggs' in stack)
974n/a
975n/a def test_custom_iterator_return(self):
976n/a # See issue #15568
977n/a class MyIter:
978n/a def __iter__(self):
979n/a return self
980n/a def __next__(self):
981n/a raise StopIteration(42)
982n/a def gen():
983n/a nonlocal ret
984n/a ret = yield from MyIter()
985n/a ret = None
986n/a list(gen())
987n/a self.assertEqual(ret, 42)
988n/a
989n/a def test_close_with_cleared_frame(self):
990n/a # See issue #17669.
991n/a #
992n/a # Create a stack of generators: outer() delegating to inner()
993n/a # delegating to innermost(). The key point is that the instance of
994n/a # inner is created first: this ensures that its frame appears before
995n/a # the instance of outer in the GC linked list.
996n/a #
997n/a # At the gc.collect call:
998n/a # - frame_clear is called on the inner_gen frame.
999n/a # - gen_dealloc is called on the outer_gen generator (the only
1000n/a # reference is in the frame's locals).
1001n/a # - gen_close is called on the outer_gen generator.
1002n/a # - gen_close_iter is called to close the inner_gen generator, which
1003n/a # in turn calls gen_close, and gen_yf.
1004n/a #
1005n/a # Previously, gen_yf would crash since inner_gen's frame had been
1006n/a # cleared (and in particular f_stacktop was NULL).
1007n/a
1008n/a def innermost():
1009n/a yield
1010n/a def inner():
1011n/a outer_gen = yield
1012n/a yield from innermost()
1013n/a def outer():
1014n/a inner_gen = yield
1015n/a yield from inner_gen
1016n/a
1017n/a with disable_gc():
1018n/a inner_gen = inner()
1019n/a outer_gen = outer()
1020n/a outer_gen.send(None)
1021n/a outer_gen.send(inner_gen)
1022n/a outer_gen.send(outer_gen)
1023n/a
1024n/a del outer_gen
1025n/a del inner_gen
1026n/a gc_collect()
1027n/a
1028n/a def test_send_tuple_with_custom_generator(self):
1029n/a # See issue #21209.
1030n/a class MyGen:
1031n/a def __iter__(self):
1032n/a return self
1033n/a def __next__(self):
1034n/a return 42
1035n/a def send(self, what):
1036n/a nonlocal v
1037n/a v = what
1038n/a return None
1039n/a def outer():
1040n/a v = yield from MyGen()
1041n/a g = outer()
1042n/a next(g)
1043n/a v = None
1044n/a g.send((1, 2, 3, 4))
1045n/a self.assertEqual(v, (1, 2, 3, 4))
1046n/a
1047n/a
1048n/aif __name__ == '__main__':
1049n/a unittest.main()