summaryrefslogtreecommitdiffstatshomepage
path: root/tests/basics/gen_yield_from_close.py
blob: 8339861056f4400c1036787c04bc7a7eb22c69d4 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
def gen():
    yield 1
    yield 2
    yield 3
    yield 4

def gen2():
    yield -1
    print((yield from gen()))
    yield 10
    yield 11

g = gen2()
print(next(g))
print(next(g))
g.close()
try:
    print(next(g))
except StopIteration:
    print("StopIteration")


# Now variation of same test, but with leaf generator
# swallowing GeneratorExit exception - its upstream gen
# generator should still receive one.
def gen3():
    yield 1
    try:
        yield 2
    except GeneratorExit:
        print("leaf caught GeneratorExit and swallowed it")
        return
    yield 3
    yield 4

def gen4():
    yield -1
    try:
        print((yield from gen3()))
    except GeneratorExit:
        print("delegating caught GeneratorExit")
        raise
    yield 10
    yield 11

g = gen4()
print(next(g))
print(next(g))
print(next(g))
g.close()
try:
    print(next(g))
except StopIteration:
    print("StopIteration")


# Yet another variation - leaf generator gets GeneratorExit,
# but raises StopIteration instead. This still should close chain properly.
def gen5():
    yield 1
    try:
        yield 2
    except GeneratorExit:
        print("leaf caught GeneratorExit and raised StopIteration instead")
        raise StopIteration(123)
    yield 3
    yield 4

def gen6():
    yield -1
    try:
        print((yield from gen5()))
    except GeneratorExit:
        print("delegating caught GeneratorExit")
        raise
    yield 10
    yield 11

g = gen6()
print(next(g))
print(next(g))
print(next(g))
g.close()
try:
    print(next(g))
except StopIteration:
    print("StopIteration")

# case where generator ignores the close request and yields instead
def gen7():
    try:
        yield 123
    except GeneratorExit:
        yield 456

g = gen7()
print(next(g))
try:
    g.close()
except RuntimeError:
    print('RuntimeError')

# case where close is propagated up to a built-in iterator
def gen8():
    g = range(2)
    yield from g
g = gen8()
print(next(g))
g.close()

# case with a user-defined close method
class Iter:
    def __iter__(self):
        return self
    def __next__(self):
        return 1
    def close(self):
        print('close')
def gen9():
    yield from Iter()
g = gen9()
print(next(g))
g.close()