17db96d56Sopenharmony_ci# -*- coding: utf-8 -*- 27db96d56Sopenharmony_ci 37db96d56Sopenharmony_ci""" 47db96d56Sopenharmony_ciTest suite for PEP 380 implementation 57db96d56Sopenharmony_ci 67db96d56Sopenharmony_ciadapted from original tests written by Greg Ewing 77db96d56Sopenharmony_cisee <http://www.cosc.canterbury.ac.nz/greg.ewing/python/yield-from/YieldFrom-Python3.1.2-rev5.zip> 87db96d56Sopenharmony_ci""" 97db96d56Sopenharmony_ci 107db96d56Sopenharmony_ciimport unittest 117db96d56Sopenharmony_ciimport inspect 127db96d56Sopenharmony_ci 137db96d56Sopenharmony_cifrom test.support import captured_stderr, disable_gc, gc_collect 147db96d56Sopenharmony_cifrom test import support 157db96d56Sopenharmony_ci 167db96d56Sopenharmony_ciclass TestPEP380Operation(unittest.TestCase): 177db96d56Sopenharmony_ci """ 187db96d56Sopenharmony_ci Test semantics. 197db96d56Sopenharmony_ci """ 207db96d56Sopenharmony_ci 217db96d56Sopenharmony_ci def test_delegation_of_initial_next_to_subgenerator(self): 227db96d56Sopenharmony_ci """ 237db96d56Sopenharmony_ci Test delegation of initial next() call to subgenerator 247db96d56Sopenharmony_ci """ 257db96d56Sopenharmony_ci trace = [] 267db96d56Sopenharmony_ci def g1(): 277db96d56Sopenharmony_ci trace.append("Starting g1") 287db96d56Sopenharmony_ci yield from g2() 297db96d56Sopenharmony_ci trace.append("Finishing g1") 307db96d56Sopenharmony_ci def g2(): 317db96d56Sopenharmony_ci trace.append("Starting g2") 327db96d56Sopenharmony_ci yield 42 337db96d56Sopenharmony_ci trace.append("Finishing g2") 347db96d56Sopenharmony_ci for x in g1(): 357db96d56Sopenharmony_ci trace.append("Yielded %s" % (x,)) 367db96d56Sopenharmony_ci self.assertEqual(trace,[ 377db96d56Sopenharmony_ci "Starting g1", 387db96d56Sopenharmony_ci "Starting g2", 397db96d56Sopenharmony_ci "Yielded 42", 407db96d56Sopenharmony_ci "Finishing g2", 417db96d56Sopenharmony_ci "Finishing g1", 427db96d56Sopenharmony_ci ]) 437db96d56Sopenharmony_ci 447db96d56Sopenharmony_ci def test_raising_exception_in_initial_next_call(self): 457db96d56Sopenharmony_ci """ 467db96d56Sopenharmony_ci Test raising exception in initial next() call 477db96d56Sopenharmony_ci """ 487db96d56Sopenharmony_ci trace = [] 497db96d56Sopenharmony_ci def g1(): 507db96d56Sopenharmony_ci try: 517db96d56Sopenharmony_ci trace.append("Starting g1") 527db96d56Sopenharmony_ci yield from g2() 537db96d56Sopenharmony_ci finally: 547db96d56Sopenharmony_ci trace.append("Finishing g1") 557db96d56Sopenharmony_ci def g2(): 567db96d56Sopenharmony_ci try: 577db96d56Sopenharmony_ci trace.append("Starting g2") 587db96d56Sopenharmony_ci raise ValueError("spanish inquisition occurred") 597db96d56Sopenharmony_ci finally: 607db96d56Sopenharmony_ci trace.append("Finishing g2") 617db96d56Sopenharmony_ci try: 627db96d56Sopenharmony_ci for x in g1(): 637db96d56Sopenharmony_ci trace.append("Yielded %s" % (x,)) 647db96d56Sopenharmony_ci except ValueError as e: 657db96d56Sopenharmony_ci self.assertEqual(e.args[0], "spanish inquisition occurred") 667db96d56Sopenharmony_ci else: 677db96d56Sopenharmony_ci self.fail("subgenerator failed to raise ValueError") 687db96d56Sopenharmony_ci self.assertEqual(trace,[ 697db96d56Sopenharmony_ci "Starting g1", 707db96d56Sopenharmony_ci "Starting g2", 717db96d56Sopenharmony_ci "Finishing g2", 727db96d56Sopenharmony_ci "Finishing g1", 737db96d56Sopenharmony_ci ]) 747db96d56Sopenharmony_ci 757db96d56Sopenharmony_ci def test_delegation_of_next_call_to_subgenerator(self): 767db96d56Sopenharmony_ci """ 777db96d56Sopenharmony_ci Test delegation of next() call to subgenerator 787db96d56Sopenharmony_ci """ 797db96d56Sopenharmony_ci trace = [] 807db96d56Sopenharmony_ci def g1(): 817db96d56Sopenharmony_ci trace.append("Starting g1") 827db96d56Sopenharmony_ci yield "g1 ham" 837db96d56Sopenharmony_ci yield from g2() 847db96d56Sopenharmony_ci yield "g1 eggs" 857db96d56Sopenharmony_ci trace.append("Finishing g1") 867db96d56Sopenharmony_ci def g2(): 877db96d56Sopenharmony_ci trace.append("Starting g2") 887db96d56Sopenharmony_ci yield "g2 spam" 897db96d56Sopenharmony_ci yield "g2 more spam" 907db96d56Sopenharmony_ci trace.append("Finishing g2") 917db96d56Sopenharmony_ci for x in g1(): 927db96d56Sopenharmony_ci trace.append("Yielded %s" % (x,)) 937db96d56Sopenharmony_ci self.assertEqual(trace,[ 947db96d56Sopenharmony_ci "Starting g1", 957db96d56Sopenharmony_ci "Yielded g1 ham", 967db96d56Sopenharmony_ci "Starting g2", 977db96d56Sopenharmony_ci "Yielded g2 spam", 987db96d56Sopenharmony_ci "Yielded g2 more spam", 997db96d56Sopenharmony_ci "Finishing g2", 1007db96d56Sopenharmony_ci "Yielded g1 eggs", 1017db96d56Sopenharmony_ci "Finishing g1", 1027db96d56Sopenharmony_ci ]) 1037db96d56Sopenharmony_ci 1047db96d56Sopenharmony_ci def test_raising_exception_in_delegated_next_call(self): 1057db96d56Sopenharmony_ci """ 1067db96d56Sopenharmony_ci Test raising exception in delegated next() call 1077db96d56Sopenharmony_ci """ 1087db96d56Sopenharmony_ci trace = [] 1097db96d56Sopenharmony_ci def g1(): 1107db96d56Sopenharmony_ci try: 1117db96d56Sopenharmony_ci trace.append("Starting g1") 1127db96d56Sopenharmony_ci yield "g1 ham" 1137db96d56Sopenharmony_ci yield from g2() 1147db96d56Sopenharmony_ci yield "g1 eggs" 1157db96d56Sopenharmony_ci finally: 1167db96d56Sopenharmony_ci trace.append("Finishing g1") 1177db96d56Sopenharmony_ci def g2(): 1187db96d56Sopenharmony_ci try: 1197db96d56Sopenharmony_ci trace.append("Starting g2") 1207db96d56Sopenharmony_ci yield "g2 spam" 1217db96d56Sopenharmony_ci raise ValueError("hovercraft is full of eels") 1227db96d56Sopenharmony_ci yield "g2 more spam" 1237db96d56Sopenharmony_ci finally: 1247db96d56Sopenharmony_ci trace.append("Finishing g2") 1257db96d56Sopenharmony_ci try: 1267db96d56Sopenharmony_ci for x in g1(): 1277db96d56Sopenharmony_ci trace.append("Yielded %s" % (x,)) 1287db96d56Sopenharmony_ci except ValueError as e: 1297db96d56Sopenharmony_ci self.assertEqual(e.args[0], "hovercraft is full of eels") 1307db96d56Sopenharmony_ci else: 1317db96d56Sopenharmony_ci self.fail("subgenerator failed to raise ValueError") 1327db96d56Sopenharmony_ci self.assertEqual(trace,[ 1337db96d56Sopenharmony_ci "Starting g1", 1347db96d56Sopenharmony_ci "Yielded g1 ham", 1357db96d56Sopenharmony_ci "Starting g2", 1367db96d56Sopenharmony_ci "Yielded g2 spam", 1377db96d56Sopenharmony_ci "Finishing g2", 1387db96d56Sopenharmony_ci "Finishing g1", 1397db96d56Sopenharmony_ci ]) 1407db96d56Sopenharmony_ci 1417db96d56Sopenharmony_ci def test_delegation_of_send(self): 1427db96d56Sopenharmony_ci """ 1437db96d56Sopenharmony_ci Test delegation of send() 1447db96d56Sopenharmony_ci """ 1457db96d56Sopenharmony_ci trace = [] 1467db96d56Sopenharmony_ci def g1(): 1477db96d56Sopenharmony_ci trace.append("Starting g1") 1487db96d56Sopenharmony_ci x = yield "g1 ham" 1497db96d56Sopenharmony_ci trace.append("g1 received %s" % (x,)) 1507db96d56Sopenharmony_ci yield from g2() 1517db96d56Sopenharmony_ci x = yield "g1 eggs" 1527db96d56Sopenharmony_ci trace.append("g1 received %s" % (x,)) 1537db96d56Sopenharmony_ci trace.append("Finishing g1") 1547db96d56Sopenharmony_ci def g2(): 1557db96d56Sopenharmony_ci trace.append("Starting g2") 1567db96d56Sopenharmony_ci x = yield "g2 spam" 1577db96d56Sopenharmony_ci trace.append("g2 received %s" % (x,)) 1587db96d56Sopenharmony_ci x = yield "g2 more spam" 1597db96d56Sopenharmony_ci trace.append("g2 received %s" % (x,)) 1607db96d56Sopenharmony_ci trace.append("Finishing g2") 1617db96d56Sopenharmony_ci g = g1() 1627db96d56Sopenharmony_ci y = next(g) 1637db96d56Sopenharmony_ci x = 1 1647db96d56Sopenharmony_ci try: 1657db96d56Sopenharmony_ci while 1: 1667db96d56Sopenharmony_ci y = g.send(x) 1677db96d56Sopenharmony_ci trace.append("Yielded %s" % (y,)) 1687db96d56Sopenharmony_ci x += 1 1697db96d56Sopenharmony_ci except StopIteration: 1707db96d56Sopenharmony_ci pass 1717db96d56Sopenharmony_ci self.assertEqual(trace,[ 1727db96d56Sopenharmony_ci "Starting g1", 1737db96d56Sopenharmony_ci "g1 received 1", 1747db96d56Sopenharmony_ci "Starting g2", 1757db96d56Sopenharmony_ci "Yielded g2 spam", 1767db96d56Sopenharmony_ci "g2 received 2", 1777db96d56Sopenharmony_ci "Yielded g2 more spam", 1787db96d56Sopenharmony_ci "g2 received 3", 1797db96d56Sopenharmony_ci "Finishing g2", 1807db96d56Sopenharmony_ci "Yielded g1 eggs", 1817db96d56Sopenharmony_ci "g1 received 4", 1827db96d56Sopenharmony_ci "Finishing g1", 1837db96d56Sopenharmony_ci ]) 1847db96d56Sopenharmony_ci 1857db96d56Sopenharmony_ci def test_handling_exception_while_delegating_send(self): 1867db96d56Sopenharmony_ci """ 1877db96d56Sopenharmony_ci Test handling exception while delegating 'send' 1887db96d56Sopenharmony_ci """ 1897db96d56Sopenharmony_ci trace = [] 1907db96d56Sopenharmony_ci def g1(): 1917db96d56Sopenharmony_ci trace.append("Starting g1") 1927db96d56Sopenharmony_ci x = yield "g1 ham" 1937db96d56Sopenharmony_ci trace.append("g1 received %s" % (x,)) 1947db96d56Sopenharmony_ci yield from g2() 1957db96d56Sopenharmony_ci x = yield "g1 eggs" 1967db96d56Sopenharmony_ci trace.append("g1 received %s" % (x,)) 1977db96d56Sopenharmony_ci trace.append("Finishing g1") 1987db96d56Sopenharmony_ci def g2(): 1997db96d56Sopenharmony_ci trace.append("Starting g2") 2007db96d56Sopenharmony_ci x = yield "g2 spam" 2017db96d56Sopenharmony_ci trace.append("g2 received %s" % (x,)) 2027db96d56Sopenharmony_ci raise ValueError("hovercraft is full of eels") 2037db96d56Sopenharmony_ci x = yield "g2 more spam" 2047db96d56Sopenharmony_ci trace.append("g2 received %s" % (x,)) 2057db96d56Sopenharmony_ci trace.append("Finishing g2") 2067db96d56Sopenharmony_ci def run(): 2077db96d56Sopenharmony_ci g = g1() 2087db96d56Sopenharmony_ci y = next(g) 2097db96d56Sopenharmony_ci x = 1 2107db96d56Sopenharmony_ci try: 2117db96d56Sopenharmony_ci while 1: 2127db96d56Sopenharmony_ci y = g.send(x) 2137db96d56Sopenharmony_ci trace.append("Yielded %s" % (y,)) 2147db96d56Sopenharmony_ci x += 1 2157db96d56Sopenharmony_ci except StopIteration: 2167db96d56Sopenharmony_ci trace.append("StopIteration") 2177db96d56Sopenharmony_ci self.assertRaises(ValueError,run) 2187db96d56Sopenharmony_ci self.assertEqual(trace,[ 2197db96d56Sopenharmony_ci "Starting g1", 2207db96d56Sopenharmony_ci "g1 received 1", 2217db96d56Sopenharmony_ci "Starting g2", 2227db96d56Sopenharmony_ci "Yielded g2 spam", 2237db96d56Sopenharmony_ci "g2 received 2", 2247db96d56Sopenharmony_ci ]) 2257db96d56Sopenharmony_ci 2267db96d56Sopenharmony_ci def test_delegating_close(self): 2277db96d56Sopenharmony_ci """ 2287db96d56Sopenharmony_ci Test delegating 'close' 2297db96d56Sopenharmony_ci """ 2307db96d56Sopenharmony_ci trace = [] 2317db96d56Sopenharmony_ci def g1(): 2327db96d56Sopenharmony_ci try: 2337db96d56Sopenharmony_ci trace.append("Starting g1") 2347db96d56Sopenharmony_ci yield "g1 ham" 2357db96d56Sopenharmony_ci yield from g2() 2367db96d56Sopenharmony_ci yield "g1 eggs" 2377db96d56Sopenharmony_ci finally: 2387db96d56Sopenharmony_ci trace.append("Finishing g1") 2397db96d56Sopenharmony_ci def g2(): 2407db96d56Sopenharmony_ci try: 2417db96d56Sopenharmony_ci trace.append("Starting g2") 2427db96d56Sopenharmony_ci yield "g2 spam" 2437db96d56Sopenharmony_ci yield "g2 more spam" 2447db96d56Sopenharmony_ci finally: 2457db96d56Sopenharmony_ci trace.append("Finishing g2") 2467db96d56Sopenharmony_ci g = g1() 2477db96d56Sopenharmony_ci for i in range(2): 2487db96d56Sopenharmony_ci x = next(g) 2497db96d56Sopenharmony_ci trace.append("Yielded %s" % (x,)) 2507db96d56Sopenharmony_ci g.close() 2517db96d56Sopenharmony_ci self.assertEqual(trace,[ 2527db96d56Sopenharmony_ci "Starting g1", 2537db96d56Sopenharmony_ci "Yielded g1 ham", 2547db96d56Sopenharmony_ci "Starting g2", 2557db96d56Sopenharmony_ci "Yielded g2 spam", 2567db96d56Sopenharmony_ci "Finishing g2", 2577db96d56Sopenharmony_ci "Finishing g1" 2587db96d56Sopenharmony_ci ]) 2597db96d56Sopenharmony_ci 2607db96d56Sopenharmony_ci def test_handing_exception_while_delegating_close(self): 2617db96d56Sopenharmony_ci """ 2627db96d56Sopenharmony_ci Test handling exception while delegating 'close' 2637db96d56Sopenharmony_ci """ 2647db96d56Sopenharmony_ci trace = [] 2657db96d56Sopenharmony_ci def g1(): 2667db96d56Sopenharmony_ci try: 2677db96d56Sopenharmony_ci trace.append("Starting g1") 2687db96d56Sopenharmony_ci yield "g1 ham" 2697db96d56Sopenharmony_ci yield from g2() 2707db96d56Sopenharmony_ci yield "g1 eggs" 2717db96d56Sopenharmony_ci finally: 2727db96d56Sopenharmony_ci trace.append("Finishing g1") 2737db96d56Sopenharmony_ci def g2(): 2747db96d56Sopenharmony_ci try: 2757db96d56Sopenharmony_ci trace.append("Starting g2") 2767db96d56Sopenharmony_ci yield "g2 spam" 2777db96d56Sopenharmony_ci yield "g2 more spam" 2787db96d56Sopenharmony_ci finally: 2797db96d56Sopenharmony_ci trace.append("Finishing g2") 2807db96d56Sopenharmony_ci raise ValueError("nybbles have exploded with delight") 2817db96d56Sopenharmony_ci try: 2827db96d56Sopenharmony_ci g = g1() 2837db96d56Sopenharmony_ci for i in range(2): 2847db96d56Sopenharmony_ci x = next(g) 2857db96d56Sopenharmony_ci trace.append("Yielded %s" % (x,)) 2867db96d56Sopenharmony_ci g.close() 2877db96d56Sopenharmony_ci except ValueError as e: 2887db96d56Sopenharmony_ci self.assertEqual(e.args[0], "nybbles have exploded with delight") 2897db96d56Sopenharmony_ci self.assertIsInstance(e.__context__, GeneratorExit) 2907db96d56Sopenharmony_ci else: 2917db96d56Sopenharmony_ci self.fail("subgenerator failed to raise ValueError") 2927db96d56Sopenharmony_ci self.assertEqual(trace,[ 2937db96d56Sopenharmony_ci "Starting g1", 2947db96d56Sopenharmony_ci "Yielded g1 ham", 2957db96d56Sopenharmony_ci "Starting g2", 2967db96d56Sopenharmony_ci "Yielded g2 spam", 2977db96d56Sopenharmony_ci "Finishing g2", 2987db96d56Sopenharmony_ci "Finishing g1", 2997db96d56Sopenharmony_ci ]) 3007db96d56Sopenharmony_ci 3017db96d56Sopenharmony_ci def test_delegating_throw(self): 3027db96d56Sopenharmony_ci """ 3037db96d56Sopenharmony_ci Test delegating 'throw' 3047db96d56Sopenharmony_ci """ 3057db96d56Sopenharmony_ci trace = [] 3067db96d56Sopenharmony_ci def g1(): 3077db96d56Sopenharmony_ci try: 3087db96d56Sopenharmony_ci trace.append("Starting g1") 3097db96d56Sopenharmony_ci yield "g1 ham" 3107db96d56Sopenharmony_ci yield from g2() 3117db96d56Sopenharmony_ci yield "g1 eggs" 3127db96d56Sopenharmony_ci finally: 3137db96d56Sopenharmony_ci trace.append("Finishing g1") 3147db96d56Sopenharmony_ci def g2(): 3157db96d56Sopenharmony_ci try: 3167db96d56Sopenharmony_ci trace.append("Starting g2") 3177db96d56Sopenharmony_ci yield "g2 spam" 3187db96d56Sopenharmony_ci yield "g2 more spam" 3197db96d56Sopenharmony_ci finally: 3207db96d56Sopenharmony_ci trace.append("Finishing g2") 3217db96d56Sopenharmony_ci try: 3227db96d56Sopenharmony_ci g = g1() 3237db96d56Sopenharmony_ci for i in range(2): 3247db96d56Sopenharmony_ci x = next(g) 3257db96d56Sopenharmony_ci trace.append("Yielded %s" % (x,)) 3267db96d56Sopenharmony_ci e = ValueError("tomato ejected") 3277db96d56Sopenharmony_ci g.throw(e) 3287db96d56Sopenharmony_ci except ValueError as e: 3297db96d56Sopenharmony_ci self.assertEqual(e.args[0], "tomato ejected") 3307db96d56Sopenharmony_ci else: 3317db96d56Sopenharmony_ci self.fail("subgenerator failed to raise ValueError") 3327db96d56Sopenharmony_ci self.assertEqual(trace,[ 3337db96d56Sopenharmony_ci "Starting g1", 3347db96d56Sopenharmony_ci "Yielded g1 ham", 3357db96d56Sopenharmony_ci "Starting g2", 3367db96d56Sopenharmony_ci "Yielded g2 spam", 3377db96d56Sopenharmony_ci "Finishing g2", 3387db96d56Sopenharmony_ci "Finishing g1", 3397db96d56Sopenharmony_ci ]) 3407db96d56Sopenharmony_ci 3417db96d56Sopenharmony_ci def test_value_attribute_of_StopIteration_exception(self): 3427db96d56Sopenharmony_ci """ 3437db96d56Sopenharmony_ci Test 'value' attribute of StopIteration exception 3447db96d56Sopenharmony_ci """ 3457db96d56Sopenharmony_ci trace = [] 3467db96d56Sopenharmony_ci def pex(e): 3477db96d56Sopenharmony_ci trace.append("%s: %s" % (e.__class__.__name__, e)) 3487db96d56Sopenharmony_ci trace.append("value = %s" % (e.value,)) 3497db96d56Sopenharmony_ci e = StopIteration() 3507db96d56Sopenharmony_ci pex(e) 3517db96d56Sopenharmony_ci e = StopIteration("spam") 3527db96d56Sopenharmony_ci pex(e) 3537db96d56Sopenharmony_ci e.value = "eggs" 3547db96d56Sopenharmony_ci pex(e) 3557db96d56Sopenharmony_ci self.assertEqual(trace,[ 3567db96d56Sopenharmony_ci "StopIteration: ", 3577db96d56Sopenharmony_ci "value = None", 3587db96d56Sopenharmony_ci "StopIteration: spam", 3597db96d56Sopenharmony_ci "value = spam", 3607db96d56Sopenharmony_ci "StopIteration: spam", 3617db96d56Sopenharmony_ci "value = eggs", 3627db96d56Sopenharmony_ci ]) 3637db96d56Sopenharmony_ci 3647db96d56Sopenharmony_ci 3657db96d56Sopenharmony_ci def test_exception_value_crash(self): 3667db96d56Sopenharmony_ci # There used to be a refcount error when the return value 3677db96d56Sopenharmony_ci # stored in the StopIteration has a refcount of 1. 3687db96d56Sopenharmony_ci def g1(): 3697db96d56Sopenharmony_ci yield from g2() 3707db96d56Sopenharmony_ci def g2(): 3717db96d56Sopenharmony_ci yield "g2" 3727db96d56Sopenharmony_ci return [42] 3737db96d56Sopenharmony_ci self.assertEqual(list(g1()), ["g2"]) 3747db96d56Sopenharmony_ci 3757db96d56Sopenharmony_ci 3767db96d56Sopenharmony_ci def test_generator_return_value(self): 3777db96d56Sopenharmony_ci """ 3787db96d56Sopenharmony_ci Test generator return value 3797db96d56Sopenharmony_ci """ 3807db96d56Sopenharmony_ci trace = [] 3817db96d56Sopenharmony_ci def g1(): 3827db96d56Sopenharmony_ci trace.append("Starting g1") 3837db96d56Sopenharmony_ci yield "g1 ham" 3847db96d56Sopenharmony_ci ret = yield from g2() 3857db96d56Sopenharmony_ci trace.append("g2 returned %r" % (ret,)) 3867db96d56Sopenharmony_ci for v in 1, (2,), StopIteration(3): 3877db96d56Sopenharmony_ci ret = yield from g2(v) 3887db96d56Sopenharmony_ci trace.append("g2 returned %r" % (ret,)) 3897db96d56Sopenharmony_ci yield "g1 eggs" 3907db96d56Sopenharmony_ci trace.append("Finishing g1") 3917db96d56Sopenharmony_ci def g2(v = None): 3927db96d56Sopenharmony_ci trace.append("Starting g2") 3937db96d56Sopenharmony_ci yield "g2 spam" 3947db96d56Sopenharmony_ci yield "g2 more spam" 3957db96d56Sopenharmony_ci trace.append("Finishing g2") 3967db96d56Sopenharmony_ci if v: 3977db96d56Sopenharmony_ci return v 3987db96d56Sopenharmony_ci for x in g1(): 3997db96d56Sopenharmony_ci trace.append("Yielded %s" % (x,)) 4007db96d56Sopenharmony_ci self.assertEqual(trace,[ 4017db96d56Sopenharmony_ci "Starting g1", 4027db96d56Sopenharmony_ci "Yielded g1 ham", 4037db96d56Sopenharmony_ci "Starting g2", 4047db96d56Sopenharmony_ci "Yielded g2 spam", 4057db96d56Sopenharmony_ci "Yielded g2 more spam", 4067db96d56Sopenharmony_ci "Finishing g2", 4077db96d56Sopenharmony_ci "g2 returned None", 4087db96d56Sopenharmony_ci "Starting g2", 4097db96d56Sopenharmony_ci "Yielded g2 spam", 4107db96d56Sopenharmony_ci "Yielded g2 more spam", 4117db96d56Sopenharmony_ci "Finishing g2", 4127db96d56Sopenharmony_ci "g2 returned 1", 4137db96d56Sopenharmony_ci "Starting g2", 4147db96d56Sopenharmony_ci "Yielded g2 spam", 4157db96d56Sopenharmony_ci "Yielded g2 more spam", 4167db96d56Sopenharmony_ci "Finishing g2", 4177db96d56Sopenharmony_ci "g2 returned (2,)", 4187db96d56Sopenharmony_ci "Starting g2", 4197db96d56Sopenharmony_ci "Yielded g2 spam", 4207db96d56Sopenharmony_ci "Yielded g2 more spam", 4217db96d56Sopenharmony_ci "Finishing g2", 4227db96d56Sopenharmony_ci "g2 returned StopIteration(3)", 4237db96d56Sopenharmony_ci "Yielded g1 eggs", 4247db96d56Sopenharmony_ci "Finishing g1", 4257db96d56Sopenharmony_ci ]) 4267db96d56Sopenharmony_ci 4277db96d56Sopenharmony_ci def test_delegation_of_next_to_non_generator(self): 4287db96d56Sopenharmony_ci """ 4297db96d56Sopenharmony_ci Test delegation of next() to non-generator 4307db96d56Sopenharmony_ci """ 4317db96d56Sopenharmony_ci trace = [] 4327db96d56Sopenharmony_ci def g(): 4337db96d56Sopenharmony_ci yield from range(3) 4347db96d56Sopenharmony_ci for x in g(): 4357db96d56Sopenharmony_ci trace.append("Yielded %s" % (x,)) 4367db96d56Sopenharmony_ci self.assertEqual(trace,[ 4377db96d56Sopenharmony_ci "Yielded 0", 4387db96d56Sopenharmony_ci "Yielded 1", 4397db96d56Sopenharmony_ci "Yielded 2", 4407db96d56Sopenharmony_ci ]) 4417db96d56Sopenharmony_ci 4427db96d56Sopenharmony_ci 4437db96d56Sopenharmony_ci def test_conversion_of_sendNone_to_next(self): 4447db96d56Sopenharmony_ci """ 4457db96d56Sopenharmony_ci Test conversion of send(None) to next() 4467db96d56Sopenharmony_ci """ 4477db96d56Sopenharmony_ci trace = [] 4487db96d56Sopenharmony_ci def g(): 4497db96d56Sopenharmony_ci yield from range(3) 4507db96d56Sopenharmony_ci gi = g() 4517db96d56Sopenharmony_ci for x in range(3): 4527db96d56Sopenharmony_ci y = gi.send(None) 4537db96d56Sopenharmony_ci trace.append("Yielded: %s" % (y,)) 4547db96d56Sopenharmony_ci self.assertEqual(trace,[ 4557db96d56Sopenharmony_ci "Yielded: 0", 4567db96d56Sopenharmony_ci "Yielded: 1", 4577db96d56Sopenharmony_ci "Yielded: 2", 4587db96d56Sopenharmony_ci ]) 4597db96d56Sopenharmony_ci 4607db96d56Sopenharmony_ci def test_delegation_of_close_to_non_generator(self): 4617db96d56Sopenharmony_ci """ 4627db96d56Sopenharmony_ci Test delegation of close() to non-generator 4637db96d56Sopenharmony_ci """ 4647db96d56Sopenharmony_ci trace = [] 4657db96d56Sopenharmony_ci def g(): 4667db96d56Sopenharmony_ci try: 4677db96d56Sopenharmony_ci trace.append("starting g") 4687db96d56Sopenharmony_ci yield from range(3) 4697db96d56Sopenharmony_ci trace.append("g should not be here") 4707db96d56Sopenharmony_ci finally: 4717db96d56Sopenharmony_ci trace.append("finishing g") 4727db96d56Sopenharmony_ci gi = g() 4737db96d56Sopenharmony_ci next(gi) 4747db96d56Sopenharmony_ci with captured_stderr() as output: 4757db96d56Sopenharmony_ci gi.close() 4767db96d56Sopenharmony_ci self.assertEqual(output.getvalue(), '') 4777db96d56Sopenharmony_ci self.assertEqual(trace,[ 4787db96d56Sopenharmony_ci "starting g", 4797db96d56Sopenharmony_ci "finishing g", 4807db96d56Sopenharmony_ci ]) 4817db96d56Sopenharmony_ci 4827db96d56Sopenharmony_ci def test_delegating_throw_to_non_generator(self): 4837db96d56Sopenharmony_ci """ 4847db96d56Sopenharmony_ci Test delegating 'throw' to non-generator 4857db96d56Sopenharmony_ci """ 4867db96d56Sopenharmony_ci trace = [] 4877db96d56Sopenharmony_ci def g(): 4887db96d56Sopenharmony_ci try: 4897db96d56Sopenharmony_ci trace.append("Starting g") 4907db96d56Sopenharmony_ci yield from range(10) 4917db96d56Sopenharmony_ci finally: 4927db96d56Sopenharmony_ci trace.append("Finishing g") 4937db96d56Sopenharmony_ci try: 4947db96d56Sopenharmony_ci gi = g() 4957db96d56Sopenharmony_ci for i in range(5): 4967db96d56Sopenharmony_ci x = next(gi) 4977db96d56Sopenharmony_ci trace.append("Yielded %s" % (x,)) 4987db96d56Sopenharmony_ci e = ValueError("tomato ejected") 4997db96d56Sopenharmony_ci gi.throw(e) 5007db96d56Sopenharmony_ci except ValueError as e: 5017db96d56Sopenharmony_ci self.assertEqual(e.args[0],"tomato ejected") 5027db96d56Sopenharmony_ci else: 5037db96d56Sopenharmony_ci self.fail("subgenerator failed to raise ValueError") 5047db96d56Sopenharmony_ci self.assertEqual(trace,[ 5057db96d56Sopenharmony_ci "Starting g", 5067db96d56Sopenharmony_ci "Yielded 0", 5077db96d56Sopenharmony_ci "Yielded 1", 5087db96d56Sopenharmony_ci "Yielded 2", 5097db96d56Sopenharmony_ci "Yielded 3", 5107db96d56Sopenharmony_ci "Yielded 4", 5117db96d56Sopenharmony_ci "Finishing g", 5127db96d56Sopenharmony_ci ]) 5137db96d56Sopenharmony_ci 5147db96d56Sopenharmony_ci def test_attempting_to_send_to_non_generator(self): 5157db96d56Sopenharmony_ci """ 5167db96d56Sopenharmony_ci Test attempting to send to non-generator 5177db96d56Sopenharmony_ci """ 5187db96d56Sopenharmony_ci trace = [] 5197db96d56Sopenharmony_ci def g(): 5207db96d56Sopenharmony_ci try: 5217db96d56Sopenharmony_ci trace.append("starting g") 5227db96d56Sopenharmony_ci yield from range(3) 5237db96d56Sopenharmony_ci trace.append("g should not be here") 5247db96d56Sopenharmony_ci finally: 5257db96d56Sopenharmony_ci trace.append("finishing g") 5267db96d56Sopenharmony_ci try: 5277db96d56Sopenharmony_ci gi = g() 5287db96d56Sopenharmony_ci next(gi) 5297db96d56Sopenharmony_ci for x in range(3): 5307db96d56Sopenharmony_ci y = gi.send(42) 5317db96d56Sopenharmony_ci trace.append("Should not have yielded: %s" % (y,)) 5327db96d56Sopenharmony_ci except AttributeError as e: 5337db96d56Sopenharmony_ci self.assertIn("send", e.args[0]) 5347db96d56Sopenharmony_ci else: 5357db96d56Sopenharmony_ci self.fail("was able to send into non-generator") 5367db96d56Sopenharmony_ci self.assertEqual(trace,[ 5377db96d56Sopenharmony_ci "starting g", 5387db96d56Sopenharmony_ci "finishing g", 5397db96d56Sopenharmony_ci ]) 5407db96d56Sopenharmony_ci 5417db96d56Sopenharmony_ci def test_broken_getattr_handling(self): 5427db96d56Sopenharmony_ci """ 5437db96d56Sopenharmony_ci Test subiterator with a broken getattr implementation 5447db96d56Sopenharmony_ci """ 5457db96d56Sopenharmony_ci class Broken: 5467db96d56Sopenharmony_ci def __iter__(self): 5477db96d56Sopenharmony_ci return self 5487db96d56Sopenharmony_ci def __next__(self): 5497db96d56Sopenharmony_ci return 1 5507db96d56Sopenharmony_ci def __getattr__(self, attr): 5517db96d56Sopenharmony_ci 1/0 5527db96d56Sopenharmony_ci 5537db96d56Sopenharmony_ci def g(): 5547db96d56Sopenharmony_ci yield from Broken() 5557db96d56Sopenharmony_ci 5567db96d56Sopenharmony_ci with self.assertRaises(ZeroDivisionError): 5577db96d56Sopenharmony_ci gi = g() 5587db96d56Sopenharmony_ci self.assertEqual(next(gi), 1) 5597db96d56Sopenharmony_ci gi.send(1) 5607db96d56Sopenharmony_ci 5617db96d56Sopenharmony_ci with self.assertRaises(ZeroDivisionError): 5627db96d56Sopenharmony_ci gi = g() 5637db96d56Sopenharmony_ci self.assertEqual(next(gi), 1) 5647db96d56Sopenharmony_ci gi.throw(AttributeError) 5657db96d56Sopenharmony_ci 5667db96d56Sopenharmony_ci with support.catch_unraisable_exception() as cm: 5677db96d56Sopenharmony_ci gi = g() 5687db96d56Sopenharmony_ci self.assertEqual(next(gi), 1) 5697db96d56Sopenharmony_ci gi.close() 5707db96d56Sopenharmony_ci 5717db96d56Sopenharmony_ci self.assertEqual(ZeroDivisionError, cm.unraisable.exc_type) 5727db96d56Sopenharmony_ci 5737db96d56Sopenharmony_ci def test_exception_in_initial_next_call(self): 5747db96d56Sopenharmony_ci """ 5757db96d56Sopenharmony_ci Test exception in initial next() call 5767db96d56Sopenharmony_ci """ 5777db96d56Sopenharmony_ci trace = [] 5787db96d56Sopenharmony_ci def g1(): 5797db96d56Sopenharmony_ci trace.append("g1 about to yield from g2") 5807db96d56Sopenharmony_ci yield from g2() 5817db96d56Sopenharmony_ci trace.append("g1 should not be here") 5827db96d56Sopenharmony_ci def g2(): 5837db96d56Sopenharmony_ci yield 1/0 5847db96d56Sopenharmony_ci def run(): 5857db96d56Sopenharmony_ci gi = g1() 5867db96d56Sopenharmony_ci next(gi) 5877db96d56Sopenharmony_ci self.assertRaises(ZeroDivisionError,run) 5887db96d56Sopenharmony_ci self.assertEqual(trace,[ 5897db96d56Sopenharmony_ci "g1 about to yield from g2" 5907db96d56Sopenharmony_ci ]) 5917db96d56Sopenharmony_ci 5927db96d56Sopenharmony_ci def test_attempted_yield_from_loop(self): 5937db96d56Sopenharmony_ci """ 5947db96d56Sopenharmony_ci Test attempted yield-from loop 5957db96d56Sopenharmony_ci """ 5967db96d56Sopenharmony_ci trace = [] 5977db96d56Sopenharmony_ci def g1(): 5987db96d56Sopenharmony_ci trace.append("g1: starting") 5997db96d56Sopenharmony_ci yield "y1" 6007db96d56Sopenharmony_ci trace.append("g1: about to yield from g2") 6017db96d56Sopenharmony_ci yield from g2() 6027db96d56Sopenharmony_ci trace.append("g1 should not be here") 6037db96d56Sopenharmony_ci 6047db96d56Sopenharmony_ci def g2(): 6057db96d56Sopenharmony_ci trace.append("g2: starting") 6067db96d56Sopenharmony_ci yield "y2" 6077db96d56Sopenharmony_ci trace.append("g2: about to yield from g1") 6087db96d56Sopenharmony_ci yield from gi 6097db96d56Sopenharmony_ci trace.append("g2 should not be here") 6107db96d56Sopenharmony_ci try: 6117db96d56Sopenharmony_ci gi = g1() 6127db96d56Sopenharmony_ci for y in gi: 6137db96d56Sopenharmony_ci trace.append("Yielded: %s" % (y,)) 6147db96d56Sopenharmony_ci except ValueError as e: 6157db96d56Sopenharmony_ci self.assertEqual(e.args[0],"generator already executing") 6167db96d56Sopenharmony_ci else: 6177db96d56Sopenharmony_ci self.fail("subgenerator didn't raise ValueError") 6187db96d56Sopenharmony_ci self.assertEqual(trace,[ 6197db96d56Sopenharmony_ci "g1: starting", 6207db96d56Sopenharmony_ci "Yielded: y1", 6217db96d56Sopenharmony_ci "g1: about to yield from g2", 6227db96d56Sopenharmony_ci "g2: starting", 6237db96d56Sopenharmony_ci "Yielded: y2", 6247db96d56Sopenharmony_ci "g2: about to yield from g1", 6257db96d56Sopenharmony_ci ]) 6267db96d56Sopenharmony_ci 6277db96d56Sopenharmony_ci def test_returning_value_from_delegated_throw(self): 6287db96d56Sopenharmony_ci """ 6297db96d56Sopenharmony_ci Test returning value from delegated 'throw' 6307db96d56Sopenharmony_ci """ 6317db96d56Sopenharmony_ci trace = [] 6327db96d56Sopenharmony_ci def g1(): 6337db96d56Sopenharmony_ci try: 6347db96d56Sopenharmony_ci trace.append("Starting g1") 6357db96d56Sopenharmony_ci yield "g1 ham" 6367db96d56Sopenharmony_ci yield from g2() 6377db96d56Sopenharmony_ci yield "g1 eggs" 6387db96d56Sopenharmony_ci finally: 6397db96d56Sopenharmony_ci trace.append("Finishing g1") 6407db96d56Sopenharmony_ci def g2(): 6417db96d56Sopenharmony_ci try: 6427db96d56Sopenharmony_ci trace.append("Starting g2") 6437db96d56Sopenharmony_ci yield "g2 spam" 6447db96d56Sopenharmony_ci yield "g2 more spam" 6457db96d56Sopenharmony_ci except LunchError: 6467db96d56Sopenharmony_ci trace.append("Caught LunchError in g2") 6477db96d56Sopenharmony_ci yield "g2 lunch saved" 6487db96d56Sopenharmony_ci yield "g2 yet more spam" 6497db96d56Sopenharmony_ci class LunchError(Exception): 6507db96d56Sopenharmony_ci pass 6517db96d56Sopenharmony_ci g = g1() 6527db96d56Sopenharmony_ci for i in range(2): 6537db96d56Sopenharmony_ci x = next(g) 6547db96d56Sopenharmony_ci trace.append("Yielded %s" % (x,)) 6557db96d56Sopenharmony_ci e = LunchError("tomato ejected") 6567db96d56Sopenharmony_ci g.throw(e) 6577db96d56Sopenharmony_ci for x in g: 6587db96d56Sopenharmony_ci trace.append("Yielded %s" % (x,)) 6597db96d56Sopenharmony_ci self.assertEqual(trace,[ 6607db96d56Sopenharmony_ci "Starting g1", 6617db96d56Sopenharmony_ci "Yielded g1 ham", 6627db96d56Sopenharmony_ci "Starting g2", 6637db96d56Sopenharmony_ci "Yielded g2 spam", 6647db96d56Sopenharmony_ci "Caught LunchError in g2", 6657db96d56Sopenharmony_ci "Yielded g2 yet more spam", 6667db96d56Sopenharmony_ci "Yielded g1 eggs", 6677db96d56Sopenharmony_ci "Finishing g1", 6687db96d56Sopenharmony_ci ]) 6697db96d56Sopenharmony_ci 6707db96d56Sopenharmony_ci def test_next_and_return_with_value(self): 6717db96d56Sopenharmony_ci """ 6727db96d56Sopenharmony_ci Test next and return with value 6737db96d56Sopenharmony_ci """ 6747db96d56Sopenharmony_ci trace = [] 6757db96d56Sopenharmony_ci def f(r): 6767db96d56Sopenharmony_ci gi = g(r) 6777db96d56Sopenharmony_ci next(gi) 6787db96d56Sopenharmony_ci try: 6797db96d56Sopenharmony_ci trace.append("f resuming g") 6807db96d56Sopenharmony_ci next(gi) 6817db96d56Sopenharmony_ci trace.append("f SHOULD NOT BE HERE") 6827db96d56Sopenharmony_ci except StopIteration as e: 6837db96d56Sopenharmony_ci trace.append("f caught %r" % (e,)) 6847db96d56Sopenharmony_ci def g(r): 6857db96d56Sopenharmony_ci trace.append("g starting") 6867db96d56Sopenharmony_ci yield 6877db96d56Sopenharmony_ci trace.append("g returning %r" % (r,)) 6887db96d56Sopenharmony_ci return r 6897db96d56Sopenharmony_ci f(None) 6907db96d56Sopenharmony_ci f(1) 6917db96d56Sopenharmony_ci f((2,)) 6927db96d56Sopenharmony_ci f(StopIteration(3)) 6937db96d56Sopenharmony_ci self.assertEqual(trace,[ 6947db96d56Sopenharmony_ci "g starting", 6957db96d56Sopenharmony_ci "f resuming g", 6967db96d56Sopenharmony_ci "g returning None", 6977db96d56Sopenharmony_ci "f caught StopIteration()", 6987db96d56Sopenharmony_ci "g starting", 6997db96d56Sopenharmony_ci "f resuming g", 7007db96d56Sopenharmony_ci "g returning 1", 7017db96d56Sopenharmony_ci "f caught StopIteration(1)", 7027db96d56Sopenharmony_ci "g starting", 7037db96d56Sopenharmony_ci "f resuming g", 7047db96d56Sopenharmony_ci "g returning (2,)", 7057db96d56Sopenharmony_ci "f caught StopIteration((2,))", 7067db96d56Sopenharmony_ci "g starting", 7077db96d56Sopenharmony_ci "f resuming g", 7087db96d56Sopenharmony_ci "g returning StopIteration(3)", 7097db96d56Sopenharmony_ci "f caught StopIteration(StopIteration(3))", 7107db96d56Sopenharmony_ci ]) 7117db96d56Sopenharmony_ci 7127db96d56Sopenharmony_ci def test_send_and_return_with_value(self): 7137db96d56Sopenharmony_ci """ 7147db96d56Sopenharmony_ci Test send and return with value 7157db96d56Sopenharmony_ci """ 7167db96d56Sopenharmony_ci trace = [] 7177db96d56Sopenharmony_ci def f(r): 7187db96d56Sopenharmony_ci gi = g(r) 7197db96d56Sopenharmony_ci next(gi) 7207db96d56Sopenharmony_ci try: 7217db96d56Sopenharmony_ci trace.append("f sending spam to g") 7227db96d56Sopenharmony_ci gi.send("spam") 7237db96d56Sopenharmony_ci trace.append("f SHOULD NOT BE HERE") 7247db96d56Sopenharmony_ci except StopIteration as e: 7257db96d56Sopenharmony_ci trace.append("f caught %r" % (e,)) 7267db96d56Sopenharmony_ci def g(r): 7277db96d56Sopenharmony_ci trace.append("g starting") 7287db96d56Sopenharmony_ci x = yield 7297db96d56Sopenharmony_ci trace.append("g received %r" % (x,)) 7307db96d56Sopenharmony_ci trace.append("g returning %r" % (r,)) 7317db96d56Sopenharmony_ci return r 7327db96d56Sopenharmony_ci f(None) 7337db96d56Sopenharmony_ci f(1) 7347db96d56Sopenharmony_ci f((2,)) 7357db96d56Sopenharmony_ci f(StopIteration(3)) 7367db96d56Sopenharmony_ci self.assertEqual(trace, [ 7377db96d56Sopenharmony_ci "g starting", 7387db96d56Sopenharmony_ci "f sending spam to g", 7397db96d56Sopenharmony_ci "g received 'spam'", 7407db96d56Sopenharmony_ci "g returning None", 7417db96d56Sopenharmony_ci "f caught StopIteration()", 7427db96d56Sopenharmony_ci "g starting", 7437db96d56Sopenharmony_ci "f sending spam to g", 7447db96d56Sopenharmony_ci "g received 'spam'", 7457db96d56Sopenharmony_ci "g returning 1", 7467db96d56Sopenharmony_ci 'f caught StopIteration(1)', 7477db96d56Sopenharmony_ci 'g starting', 7487db96d56Sopenharmony_ci 'f sending spam to g', 7497db96d56Sopenharmony_ci "g received 'spam'", 7507db96d56Sopenharmony_ci 'g returning (2,)', 7517db96d56Sopenharmony_ci 'f caught StopIteration((2,))', 7527db96d56Sopenharmony_ci 'g starting', 7537db96d56Sopenharmony_ci 'f sending spam to g', 7547db96d56Sopenharmony_ci "g received 'spam'", 7557db96d56Sopenharmony_ci 'g returning StopIteration(3)', 7567db96d56Sopenharmony_ci 'f caught StopIteration(StopIteration(3))' 7577db96d56Sopenharmony_ci ]) 7587db96d56Sopenharmony_ci 7597db96d56Sopenharmony_ci def test_catching_exception_from_subgen_and_returning(self): 7607db96d56Sopenharmony_ci """ 7617db96d56Sopenharmony_ci Test catching an exception thrown into a 7627db96d56Sopenharmony_ci subgenerator and returning a value 7637db96d56Sopenharmony_ci """ 7647db96d56Sopenharmony_ci def inner(): 7657db96d56Sopenharmony_ci try: 7667db96d56Sopenharmony_ci yield 1 7677db96d56Sopenharmony_ci except ValueError: 7687db96d56Sopenharmony_ci trace.append("inner caught ValueError") 7697db96d56Sopenharmony_ci return value 7707db96d56Sopenharmony_ci 7717db96d56Sopenharmony_ci def outer(): 7727db96d56Sopenharmony_ci v = yield from inner() 7737db96d56Sopenharmony_ci trace.append("inner returned %r to outer" % (v,)) 7747db96d56Sopenharmony_ci yield v 7757db96d56Sopenharmony_ci 7767db96d56Sopenharmony_ci for value in 2, (2,), StopIteration(2): 7777db96d56Sopenharmony_ci trace = [] 7787db96d56Sopenharmony_ci g = outer() 7797db96d56Sopenharmony_ci trace.append(next(g)) 7807db96d56Sopenharmony_ci trace.append(repr(g.throw(ValueError))) 7817db96d56Sopenharmony_ci self.assertEqual(trace, [ 7827db96d56Sopenharmony_ci 1, 7837db96d56Sopenharmony_ci "inner caught ValueError", 7847db96d56Sopenharmony_ci "inner returned %r to outer" % (value,), 7857db96d56Sopenharmony_ci repr(value), 7867db96d56Sopenharmony_ci ]) 7877db96d56Sopenharmony_ci 7887db96d56Sopenharmony_ci def test_throwing_GeneratorExit_into_subgen_that_returns(self): 7897db96d56Sopenharmony_ci """ 7907db96d56Sopenharmony_ci Test throwing GeneratorExit into a subgenerator that 7917db96d56Sopenharmony_ci catches it and returns normally. 7927db96d56Sopenharmony_ci """ 7937db96d56Sopenharmony_ci trace = [] 7947db96d56Sopenharmony_ci def f(): 7957db96d56Sopenharmony_ci try: 7967db96d56Sopenharmony_ci trace.append("Enter f") 7977db96d56Sopenharmony_ci yield 7987db96d56Sopenharmony_ci trace.append("Exit f") 7997db96d56Sopenharmony_ci except GeneratorExit: 8007db96d56Sopenharmony_ci return 8017db96d56Sopenharmony_ci def g(): 8027db96d56Sopenharmony_ci trace.append("Enter g") 8037db96d56Sopenharmony_ci yield from f() 8047db96d56Sopenharmony_ci trace.append("Exit g") 8057db96d56Sopenharmony_ci try: 8067db96d56Sopenharmony_ci gi = g() 8077db96d56Sopenharmony_ci next(gi) 8087db96d56Sopenharmony_ci gi.throw(GeneratorExit) 8097db96d56Sopenharmony_ci except GeneratorExit: 8107db96d56Sopenharmony_ci pass 8117db96d56Sopenharmony_ci else: 8127db96d56Sopenharmony_ci self.fail("subgenerator failed to raise GeneratorExit") 8137db96d56Sopenharmony_ci self.assertEqual(trace,[ 8147db96d56Sopenharmony_ci "Enter g", 8157db96d56Sopenharmony_ci "Enter f", 8167db96d56Sopenharmony_ci ]) 8177db96d56Sopenharmony_ci 8187db96d56Sopenharmony_ci def test_throwing_GeneratorExit_into_subgenerator_that_yields(self): 8197db96d56Sopenharmony_ci """ 8207db96d56Sopenharmony_ci Test throwing GeneratorExit into a subgenerator that 8217db96d56Sopenharmony_ci catches it and yields. 8227db96d56Sopenharmony_ci """ 8237db96d56Sopenharmony_ci trace = [] 8247db96d56Sopenharmony_ci def f(): 8257db96d56Sopenharmony_ci try: 8267db96d56Sopenharmony_ci trace.append("Enter f") 8277db96d56Sopenharmony_ci yield 8287db96d56Sopenharmony_ci trace.append("Exit f") 8297db96d56Sopenharmony_ci except GeneratorExit: 8307db96d56Sopenharmony_ci yield 8317db96d56Sopenharmony_ci def g(): 8327db96d56Sopenharmony_ci trace.append("Enter g") 8337db96d56Sopenharmony_ci yield from f() 8347db96d56Sopenharmony_ci trace.append("Exit g") 8357db96d56Sopenharmony_ci try: 8367db96d56Sopenharmony_ci gi = g() 8377db96d56Sopenharmony_ci next(gi) 8387db96d56Sopenharmony_ci gi.throw(GeneratorExit) 8397db96d56Sopenharmony_ci except RuntimeError as e: 8407db96d56Sopenharmony_ci self.assertEqual(e.args[0], "generator ignored GeneratorExit") 8417db96d56Sopenharmony_ci else: 8427db96d56Sopenharmony_ci self.fail("subgenerator failed to raise GeneratorExit") 8437db96d56Sopenharmony_ci self.assertEqual(trace,[ 8447db96d56Sopenharmony_ci "Enter g", 8457db96d56Sopenharmony_ci "Enter f", 8467db96d56Sopenharmony_ci ]) 8477db96d56Sopenharmony_ci 8487db96d56Sopenharmony_ci def test_throwing_GeneratorExit_into_subgen_that_raises(self): 8497db96d56Sopenharmony_ci """ 8507db96d56Sopenharmony_ci Test throwing GeneratorExit into a subgenerator that 8517db96d56Sopenharmony_ci catches it and raises a different exception. 8527db96d56Sopenharmony_ci """ 8537db96d56Sopenharmony_ci trace = [] 8547db96d56Sopenharmony_ci def f(): 8557db96d56Sopenharmony_ci try: 8567db96d56Sopenharmony_ci trace.append("Enter f") 8577db96d56Sopenharmony_ci yield 8587db96d56Sopenharmony_ci trace.append("Exit f") 8597db96d56Sopenharmony_ci except GeneratorExit: 8607db96d56Sopenharmony_ci raise ValueError("Vorpal bunny encountered") 8617db96d56Sopenharmony_ci def g(): 8627db96d56Sopenharmony_ci trace.append("Enter g") 8637db96d56Sopenharmony_ci yield from f() 8647db96d56Sopenharmony_ci trace.append("Exit g") 8657db96d56Sopenharmony_ci try: 8667db96d56Sopenharmony_ci gi = g() 8677db96d56Sopenharmony_ci next(gi) 8687db96d56Sopenharmony_ci gi.throw(GeneratorExit) 8697db96d56Sopenharmony_ci except ValueError as e: 8707db96d56Sopenharmony_ci self.assertEqual(e.args[0], "Vorpal bunny encountered") 8717db96d56Sopenharmony_ci self.assertIsInstance(e.__context__, GeneratorExit) 8727db96d56Sopenharmony_ci else: 8737db96d56Sopenharmony_ci self.fail("subgenerator failed to raise ValueError") 8747db96d56Sopenharmony_ci self.assertEqual(trace,[ 8757db96d56Sopenharmony_ci "Enter g", 8767db96d56Sopenharmony_ci "Enter f", 8777db96d56Sopenharmony_ci ]) 8787db96d56Sopenharmony_ci 8797db96d56Sopenharmony_ci def test_yield_from_empty(self): 8807db96d56Sopenharmony_ci def g(): 8817db96d56Sopenharmony_ci yield from () 8827db96d56Sopenharmony_ci self.assertRaises(StopIteration, next, g()) 8837db96d56Sopenharmony_ci 8847db96d56Sopenharmony_ci def test_delegating_generators_claim_to_be_running(self): 8857db96d56Sopenharmony_ci # Check with basic iteration 8867db96d56Sopenharmony_ci def one(): 8877db96d56Sopenharmony_ci yield 0 8887db96d56Sopenharmony_ci yield from two() 8897db96d56Sopenharmony_ci yield 3 8907db96d56Sopenharmony_ci def two(): 8917db96d56Sopenharmony_ci yield 1 8927db96d56Sopenharmony_ci try: 8937db96d56Sopenharmony_ci yield from g1 8947db96d56Sopenharmony_ci except ValueError: 8957db96d56Sopenharmony_ci pass 8967db96d56Sopenharmony_ci yield 2 8977db96d56Sopenharmony_ci g1 = one() 8987db96d56Sopenharmony_ci self.assertEqual(list(g1), [0, 1, 2, 3]) 8997db96d56Sopenharmony_ci # Check with send 9007db96d56Sopenharmony_ci g1 = one() 9017db96d56Sopenharmony_ci res = [next(g1)] 9027db96d56Sopenharmony_ci try: 9037db96d56Sopenharmony_ci while True: 9047db96d56Sopenharmony_ci res.append(g1.send(42)) 9057db96d56Sopenharmony_ci except StopIteration: 9067db96d56Sopenharmony_ci pass 9077db96d56Sopenharmony_ci self.assertEqual(res, [0, 1, 2, 3]) 9087db96d56Sopenharmony_ci # Check with throw 9097db96d56Sopenharmony_ci class MyErr(Exception): 9107db96d56Sopenharmony_ci pass 9117db96d56Sopenharmony_ci def one(): 9127db96d56Sopenharmony_ci try: 9137db96d56Sopenharmony_ci yield 0 9147db96d56Sopenharmony_ci except MyErr: 9157db96d56Sopenharmony_ci pass 9167db96d56Sopenharmony_ci yield from two() 9177db96d56Sopenharmony_ci try: 9187db96d56Sopenharmony_ci yield 3 9197db96d56Sopenharmony_ci except MyErr: 9207db96d56Sopenharmony_ci pass 9217db96d56Sopenharmony_ci def two(): 9227db96d56Sopenharmony_ci try: 9237db96d56Sopenharmony_ci yield 1 9247db96d56Sopenharmony_ci except MyErr: 9257db96d56Sopenharmony_ci pass 9267db96d56Sopenharmony_ci try: 9277db96d56Sopenharmony_ci yield from g1 9287db96d56Sopenharmony_ci except ValueError: 9297db96d56Sopenharmony_ci pass 9307db96d56Sopenharmony_ci try: 9317db96d56Sopenharmony_ci yield 2 9327db96d56Sopenharmony_ci except MyErr: 9337db96d56Sopenharmony_ci pass 9347db96d56Sopenharmony_ci g1 = one() 9357db96d56Sopenharmony_ci res = [next(g1)] 9367db96d56Sopenharmony_ci try: 9377db96d56Sopenharmony_ci while True: 9387db96d56Sopenharmony_ci res.append(g1.throw(MyErr)) 9397db96d56Sopenharmony_ci except StopIteration: 9407db96d56Sopenharmony_ci pass 9417db96d56Sopenharmony_ci except: 9427db96d56Sopenharmony_ci self.assertEqual(res, [0, 1, 2, 3]) 9437db96d56Sopenharmony_ci raise 9447db96d56Sopenharmony_ci # Check with close 9457db96d56Sopenharmony_ci class MyIt(object): 9467db96d56Sopenharmony_ci def __iter__(self): 9477db96d56Sopenharmony_ci return self 9487db96d56Sopenharmony_ci def __next__(self): 9497db96d56Sopenharmony_ci return 42 9507db96d56Sopenharmony_ci def close(self_): 9517db96d56Sopenharmony_ci self.assertTrue(g1.gi_running) 9527db96d56Sopenharmony_ci self.assertRaises(ValueError, next, g1) 9537db96d56Sopenharmony_ci def one(): 9547db96d56Sopenharmony_ci yield from MyIt() 9557db96d56Sopenharmony_ci g1 = one() 9567db96d56Sopenharmony_ci next(g1) 9577db96d56Sopenharmony_ci g1.close() 9587db96d56Sopenharmony_ci 9597db96d56Sopenharmony_ci def test_delegator_is_visible_to_debugger(self): 9607db96d56Sopenharmony_ci def call_stack(): 9617db96d56Sopenharmony_ci return [f[3] for f in inspect.stack()] 9627db96d56Sopenharmony_ci 9637db96d56Sopenharmony_ci def gen(): 9647db96d56Sopenharmony_ci yield call_stack() 9657db96d56Sopenharmony_ci yield call_stack() 9667db96d56Sopenharmony_ci yield call_stack() 9677db96d56Sopenharmony_ci 9687db96d56Sopenharmony_ci def spam(g): 9697db96d56Sopenharmony_ci yield from g 9707db96d56Sopenharmony_ci 9717db96d56Sopenharmony_ci def eggs(g): 9727db96d56Sopenharmony_ci yield from g 9737db96d56Sopenharmony_ci 9747db96d56Sopenharmony_ci for stack in spam(gen()): 9757db96d56Sopenharmony_ci self.assertTrue('spam' in stack) 9767db96d56Sopenharmony_ci 9777db96d56Sopenharmony_ci for stack in spam(eggs(gen())): 9787db96d56Sopenharmony_ci self.assertTrue('spam' in stack and 'eggs' in stack) 9797db96d56Sopenharmony_ci 9807db96d56Sopenharmony_ci def test_custom_iterator_return(self): 9817db96d56Sopenharmony_ci # See issue #15568 9827db96d56Sopenharmony_ci class MyIter: 9837db96d56Sopenharmony_ci def __iter__(self): 9847db96d56Sopenharmony_ci return self 9857db96d56Sopenharmony_ci def __next__(self): 9867db96d56Sopenharmony_ci raise StopIteration(42) 9877db96d56Sopenharmony_ci def gen(): 9887db96d56Sopenharmony_ci nonlocal ret 9897db96d56Sopenharmony_ci ret = yield from MyIter() 9907db96d56Sopenharmony_ci ret = None 9917db96d56Sopenharmony_ci list(gen()) 9927db96d56Sopenharmony_ci self.assertEqual(ret, 42) 9937db96d56Sopenharmony_ci 9947db96d56Sopenharmony_ci def test_close_with_cleared_frame(self): 9957db96d56Sopenharmony_ci # See issue #17669. 9967db96d56Sopenharmony_ci # 9977db96d56Sopenharmony_ci # Create a stack of generators: outer() delegating to inner() 9987db96d56Sopenharmony_ci # delegating to innermost(). The key point is that the instance of 9997db96d56Sopenharmony_ci # inner is created first: this ensures that its frame appears before 10007db96d56Sopenharmony_ci # the instance of outer in the GC linked list. 10017db96d56Sopenharmony_ci # 10027db96d56Sopenharmony_ci # At the gc.collect call: 10037db96d56Sopenharmony_ci # - frame_clear is called on the inner_gen frame. 10047db96d56Sopenharmony_ci # - gen_dealloc is called on the outer_gen generator (the only 10057db96d56Sopenharmony_ci # reference is in the frame's locals). 10067db96d56Sopenharmony_ci # - gen_close is called on the outer_gen generator. 10077db96d56Sopenharmony_ci # - gen_close_iter is called to close the inner_gen generator, which 10087db96d56Sopenharmony_ci # in turn calls gen_close, and gen_yf. 10097db96d56Sopenharmony_ci # 10107db96d56Sopenharmony_ci # Previously, gen_yf would crash since inner_gen's frame had been 10117db96d56Sopenharmony_ci # cleared (and in particular f_stacktop was NULL). 10127db96d56Sopenharmony_ci 10137db96d56Sopenharmony_ci def innermost(): 10147db96d56Sopenharmony_ci yield 10157db96d56Sopenharmony_ci def inner(): 10167db96d56Sopenharmony_ci outer_gen = yield 10177db96d56Sopenharmony_ci yield from innermost() 10187db96d56Sopenharmony_ci def outer(): 10197db96d56Sopenharmony_ci inner_gen = yield 10207db96d56Sopenharmony_ci yield from inner_gen 10217db96d56Sopenharmony_ci 10227db96d56Sopenharmony_ci with disable_gc(): 10237db96d56Sopenharmony_ci inner_gen = inner() 10247db96d56Sopenharmony_ci outer_gen = outer() 10257db96d56Sopenharmony_ci outer_gen.send(None) 10267db96d56Sopenharmony_ci outer_gen.send(inner_gen) 10277db96d56Sopenharmony_ci outer_gen.send(outer_gen) 10287db96d56Sopenharmony_ci 10297db96d56Sopenharmony_ci del outer_gen 10307db96d56Sopenharmony_ci del inner_gen 10317db96d56Sopenharmony_ci gc_collect() 10327db96d56Sopenharmony_ci 10337db96d56Sopenharmony_ci def test_send_tuple_with_custom_generator(self): 10347db96d56Sopenharmony_ci # See issue #21209. 10357db96d56Sopenharmony_ci class MyGen: 10367db96d56Sopenharmony_ci def __iter__(self): 10377db96d56Sopenharmony_ci return self 10387db96d56Sopenharmony_ci def __next__(self): 10397db96d56Sopenharmony_ci return 42 10407db96d56Sopenharmony_ci def send(self, what): 10417db96d56Sopenharmony_ci nonlocal v 10427db96d56Sopenharmony_ci v = what 10437db96d56Sopenharmony_ci return None 10447db96d56Sopenharmony_ci def outer(): 10457db96d56Sopenharmony_ci v = yield from MyGen() 10467db96d56Sopenharmony_ci g = outer() 10477db96d56Sopenharmony_ci next(g) 10487db96d56Sopenharmony_ci v = None 10497db96d56Sopenharmony_ci g.send((1, 2, 3, 4)) 10507db96d56Sopenharmony_ci self.assertEqual(v, (1, 2, 3, 4)) 10517db96d56Sopenharmony_ci 10527db96d56Sopenharmony_ci 10537db96d56Sopenharmony_ciif __name__ == '__main__': 10547db96d56Sopenharmony_ci unittest.main() 1055