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