1# cython: language_level=3, binding=True
2# mode: run
3# tag: pep492, asyncfor, await
4
5
6def run_async(coro, ignore_type=False):
7    if not ignore_type:
8        #assert coro.__class__ is types.GeneratorType
9        assert coro.__class__.__name__ in ('coroutine', 'GeneratorWrapper'), coro.__class__.__name__
10
11    buffer = []
12    result = None
13    while True:
14        try:
15            buffer.append(coro.send(None))
16        except StopIteration as ex:
17            result = ex.args[0] if ex.args else None
18            break
19    return buffer, result
20
21
22def run_async__await__(coro):
23    assert coro.__class__.__name__ in ('coroutine', 'GeneratorWrapper'), coro.__class__.__name__
24    aw = coro.__await__()
25    buffer = []
26    result = None
27    i = 0
28    while True:
29        try:
30            if i % 2:
31                buffer.append(next(aw))
32            else:
33                buffer.append(aw.send(None))
34            i += 1
35        except StopIteration as ex:
36            result = ex.args[0] if ex.args else None
37            break
38    return buffer, result
39
40
41async def await_pyobject(awaitable):
42    """
43    >>> async def simple():
44    ...     return 10
45
46    >>> buffer, result = run_async(await_pyobject(simple()))
47    >>> result
48    10
49
50    >>> async def awaiting(awaitable):
51    ...     return await awaitable
52
53    >>> buffer, result = run_async(await_pyobject(awaiting(simple())))
54    >>> result
55    10
56    """
57    return await awaitable
58
59
60def await_cyobject():
61    """
62    >>> async def run_await(awaitable):
63    ...     return await awaitable
64
65    >>> simple, awaiting = await_cyobject()
66
67    >>> buffer, result = run_async(run_await(simple()))
68    >>> result
69    10
70
71    >>> buffer, result = run_async(run_await(awaiting(simple())))
72    >>> result
73    10
74
75    >>> buffer, result = run_async(run_await(awaiting(awaiting(simple()))))
76    >>> result
77    10
78
79    >>> buffer, result = run_async(run_await(awaiting(run_await(awaiting(simple())))))
80    >>> result
81    10
82    """
83
84    async def simple():
85        return 10
86
87    async def awaiting(awaitable):
88        return await awaitable
89
90    return simple, awaiting
91
92
93cimport cython
94
95def yield_from_cyobject():
96    """
97    >>> async def py_simple_nonit():
98    ...     return 10
99
100    >>> async def run_await(awaitable):
101    ...     return await awaitable
102
103    >>> def run_yield_from(it):
104    ...     return (yield from it)
105
106    >>> simple_nonit, simple_it, awaiting, yield_from = yield_from_cyobject()
107
108    >>> buffer, result = run_async(run_await(simple_it()))
109    >>> result
110    10
111    >>> buffer, result = run_async(run_await(awaiting(simple_it())))
112    >>> result
113    10
114    >>> buffer, result = run_async(awaiting(run_await(simple_it())), ignore_type=True)
115    >>> result
116    10
117    >>> buffer, result = run_async(run_await(py_simple_nonit()))
118    >>> result
119    10
120
121    >>> buffer, result = run_async(run_yield_from(awaiting(run_await(simple_it()))), ignore_type=True)
122    >>> result
123    10
124
125    >>> buffer, result = run_async(run_yield_from(simple_it()), ignore_type=True)
126    >>> result
127    10
128    >>> buffer, result = run_async(yield_from(simple_it()), ignore_type=True)
129    >>> result
130    10
131
132    >>> next(run_yield_from(simple_nonit()))  # doctest: +ELLIPSIS
133    Traceback (most recent call last):
134    TypeError: ...
135    >>> next(run_yield_from(py_simple_nonit()))  # doctest: +ELLIPSIS
136    Traceback (most recent call last):
137    TypeError: ...
138    >>> next(yield_from(py_simple_nonit()))
139    Traceback (most recent call last):
140    TypeError: 'coroutine' object is not iterable
141    """
142    async def simple_nonit():
143        return 10
144
145    @cython.iterable_coroutine
146    async def simple_it():
147        return 10
148
149    @cython.iterable_coroutine
150    async def awaiting(awaitable):
151        return await awaitable
152
153    def yield_from(it):
154        return (yield from it)
155
156    return simple_nonit, simple_it, awaiting, yield_from
157