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

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