Blame tests/run/async_iter_pep492.pyx

Packit 562c7a
# mode: run
Packit 562c7a
# tag: pep492, asyncfor, await
Packit 562c7a
Packit 562c7a
import sys
Packit 562c7a
Packit 562c7a
if sys.version_info >= (3, 5, 0, 'beta'):
Packit 562c7a
    # pass Cython implemented AsyncIter() into a Python async-for loop
Packit 562c7a
    __doc__ = u"""
Packit 562c7a
>>> def test_py35(AsyncIterClass):
Packit 562c7a
...     buffer = []
Packit 562c7a
...     async def coro():
Packit 562c7a
...         async for i1, i2 in AsyncIterClass(1):
Packit 562c7a
...             buffer.append(i1 + i2)
Packit 562c7a
...     return coro, buffer
Packit 562c7a
Packit 562c7a
>>> testfunc, buffer = test_py35(AsyncIterOld if sys.version_info < (3, 5, 2) else AsyncIter)
Packit 562c7a
>>> buffer
Packit 562c7a
[]
Packit 562c7a
Packit 562c7a
>>> yielded, _ = run_async(testfunc(), check_type=False)
Packit 562c7a
>>> yielded == [i * 100 for i in range(1, 11)] or yielded
Packit 562c7a
True
Packit 562c7a
>>> buffer == [i*2 for i in range(1, 101)] or buffer
Packit 562c7a
True
Packit 562c7a
"""
Packit 562c7a
Packit 562c7a
Packit 562c7a
cdef class AsyncYieldFrom:
Packit 562c7a
    cdef object obj
Packit 562c7a
    def __init__(self, obj):
Packit 562c7a
        self.obj = obj
Packit 562c7a
Packit 562c7a
    def __await__(self):
Packit 562c7a
        yield from self.obj
Packit 562c7a
Packit 562c7a
Packit 562c7a
cdef class AsyncYield:
Packit 562c7a
    cdef object value
Packit 562c7a
    def __init__(self, value):
Packit 562c7a
        self.value = value
Packit 562c7a
Packit 562c7a
    def __await__(self):
Packit 562c7a
        yield self.value
Packit 562c7a
Packit 562c7a
Packit 562c7a
def run_async(coro, check_type='coroutine'):
Packit 562c7a
    if check_type:
Packit 562c7a
        assert coro.__class__.__name__ == check_type, \
Packit 562c7a
            'type(%s) != %s' % (coro.__class__, check_type)
Packit 562c7a
Packit 562c7a
    buffer = []
Packit 562c7a
    result = None
Packit 562c7a
    while True:
Packit 562c7a
        try:
Packit 562c7a
            buffer.append(coro.send(None))
Packit 562c7a
        except StopIteration as ex:
Packit 562c7a
            result = ex.args[0] if ex.args else None
Packit 562c7a
            break
Packit 562c7a
    return buffer, result
Packit 562c7a
Packit 562c7a
Packit 562c7a
cdef class AsyncIter:
Packit 562c7a
    cdef long i
Packit 562c7a
    cdef long aiter_calls
Packit 562c7a
    cdef long max_iter_calls
Packit 562c7a
Packit 562c7a
    def __init__(self, long max_iter_calls=1):
Packit 562c7a
        self.i = 0
Packit 562c7a
        self.aiter_calls = 0
Packit 562c7a
        self.max_iter_calls = max_iter_calls
Packit 562c7a
Packit 562c7a
    def __aiter__(self):
Packit 562c7a
        self.aiter_calls += 1
Packit 562c7a
        return self
Packit 562c7a
Packit 562c7a
    async def __anext__(self):
Packit 562c7a
        self.i += 1
Packit 562c7a
        assert self.aiter_calls <= self.max_iter_calls
Packit 562c7a
Packit 562c7a
        if not (self.i % 10):
Packit 562c7a
            await AsyncYield(self.i * 10)
Packit 562c7a
Packit 562c7a
        if self.i > 100:
Packit 562c7a
            raise StopAsyncIteration
Packit 562c7a
Packit 562c7a
        return self.i, self.i
Packit 562c7a
Packit 562c7a
Packit 562c7a
cdef class AsyncIterOld(AsyncIter):
Packit 562c7a
    """
Packit 562c7a
    Same as AsyncIter, but with the old async-def interface for __aiter__().
Packit 562c7a
    """
Packit 562c7a
    async def __aiter__(self):
Packit 562c7a
        self.aiter_calls += 1
Packit 562c7a
        return self
Packit 562c7a
Packit 562c7a
Packit 562c7a
def test_for_1():
Packit 562c7a
    """
Packit 562c7a
    >>> testfunc, buffer = test_for_1()
Packit 562c7a
    >>> buffer
Packit 562c7a
    []
Packit 562c7a
    >>> yielded, _ = run_async(testfunc())
Packit 562c7a
    >>> yielded == [i * 100 for i in range(1, 11)] or yielded
Packit 562c7a
    True
Packit 562c7a
    >>> buffer == [i*2 for i in range(1, 101)] or buffer
Packit 562c7a
    True
Packit 562c7a
    """
Packit 562c7a
    buffer = []
Packit 562c7a
    async def test1():
Packit 562c7a
        async for i1, i2 in AsyncIter(1):
Packit 562c7a
            buffer.append(i1 + i2)
Packit 562c7a
    return test1, buffer
Packit 562c7a
Packit 562c7a
Packit 562c7a
def test_for_2():
Packit 562c7a
    """
Packit 562c7a
    >>> testfunc, buffer = test_for_2()
Packit 562c7a
    >>> buffer
Packit 562c7a
    []
Packit 562c7a
    >>> yielded, _ = run_async(testfunc())
Packit 562c7a
    >>> yielded == [100, 200] or yielded
Packit 562c7a
    True
Packit 562c7a
    >>> buffer == [i for i in range(1, 21)] + ['end'] or buffer
Packit 562c7a
    True
Packit 562c7a
    """
Packit 562c7a
    buffer = []
Packit 562c7a
    async def test2():
Packit 562c7a
        nonlocal buffer
Packit 562c7a
        async for i in AsyncIter(2):
Packit 562c7a
            buffer.append(i[0])
Packit 562c7a
            if i[0] == 20:
Packit 562c7a
                break
Packit 562c7a
        else:
Packit 562c7a
            buffer.append('what?')
Packit 562c7a
        buffer.append('end')
Packit 562c7a
    return test2, buffer
Packit 562c7a
Packit 562c7a
Packit 562c7a
Packit 562c7a
def test_for_3():
Packit 562c7a
    """
Packit 562c7a
    >>> testfunc, buffer = test_for_3()
Packit 562c7a
    >>> buffer
Packit 562c7a
    []
Packit 562c7a
    >>> yielded, _ = run_async(testfunc())
Packit 562c7a
    >>> yielded == [i * 100 for i in range(1, 11)] or yielded
Packit 562c7a
    True
Packit 562c7a
    >>> buffer == [i for i in range(1, 21)] + ['what?', 'end'] or buffer
Packit 562c7a
    True
Packit 562c7a
    """
Packit 562c7a
    buffer = []
Packit 562c7a
    async def test3():
Packit 562c7a
        nonlocal buffer
Packit 562c7a
        async for i in AsyncIter(3):
Packit 562c7a
            if i[0] > 20:
Packit 562c7a
                continue
Packit 562c7a
            buffer.append(i[0])
Packit 562c7a
        else:
Packit 562c7a
            buffer.append('what?')
Packit 562c7a
        buffer.append('end')
Packit 562c7a
    return test3, buffer
Packit 562c7a
Packit 562c7a
Packit 562c7a
cdef class NonAwaitableFromAnext:
Packit 562c7a
    def __aiter__(self):
Packit 562c7a
        return self
Packit 562c7a
Packit 562c7a
    def __anext__(self):
Packit 562c7a
        return 123
Packit 562c7a
Packit 562c7a
Packit 562c7a
def test_broken_anext():
Packit 562c7a
    """
Packit 562c7a
    >>> testfunc = test_broken_anext()
Packit 562c7a
    >>> try: run_async(testfunc())
Packit 562c7a
    ... except TypeError as exc:
Packit 562c7a
    ...     assert ' int' in str(exc)
Packit 562c7a
    ... else:
Packit 562c7a
    ...     print("NOT RAISED!")
Packit 562c7a
    """
Packit 562c7a
    async def foo():
Packit 562c7a
        async for i in NonAwaitableFromAnext():
Packit 562c7a
            print('never going to happen')
Packit 562c7a
    return foo
Packit 562c7a
Packit 562c7a
Packit 562c7a
cdef class Manager:
Packit 562c7a
    cdef readonly list counter
Packit 562c7a
    def __init__(self, counter):
Packit 562c7a
        self.counter = counter
Packit 562c7a
Packit 562c7a
    async def __aenter__(self):
Packit 562c7a
        self.counter[0] += 10000
Packit 562c7a
Packit 562c7a
    async def __aexit__(self, *args):
Packit 562c7a
        self.counter[0] += 100000
Packit 562c7a
Packit 562c7a
Packit 562c7a
cdef class Iterable:
Packit 562c7a
    cdef long i
Packit 562c7a
    def __init__(self):
Packit 562c7a
        self.i = 0
Packit 562c7a
Packit 562c7a
    def __aiter__(self):
Packit 562c7a
        return self
Packit 562c7a
Packit 562c7a
    async def __anext__(self):
Packit 562c7a
        if self.i > 10:
Packit 562c7a
            raise StopAsyncIteration
Packit 562c7a
        self.i += 1
Packit 562c7a
        return self.i
Packit 562c7a
Packit 562c7a
Packit 562c7a
def test_with_for():
Packit 562c7a
    """
Packit 562c7a
    >>> test_with_for()
Packit 562c7a
    111011
Packit 562c7a
    333033
Packit 562c7a
    20555255
Packit 562c7a
    """
Packit 562c7a
    I = [0]
Packit 562c7a
Packit 562c7a
    manager = Manager(I)
Packit 562c7a
    iterable = Iterable()
Packit 562c7a
    mrefs_before = sys.getrefcount(manager)
Packit 562c7a
    irefs_before = sys.getrefcount(iterable)
Packit 562c7a
Packit 562c7a
    async def main():
Packit 562c7a
        async with manager:
Packit 562c7a
            async for i in iterable:
Packit 562c7a
                I[0] += 1
Packit 562c7a
        I[0] += 1000
Packit 562c7a
Packit 562c7a
    run_async(main())
Packit 562c7a
    print(I[0])
Packit 562c7a
Packit 562c7a
    assert sys.getrefcount(manager) == mrefs_before
Packit 562c7a
    assert sys.getrefcount(iterable) == irefs_before
Packit 562c7a
Packit 562c7a
    ##############
Packit 562c7a
Packit 562c7a
    async def main():
Packit 562c7a
        nonlocal I
Packit 562c7a
Packit 562c7a
        async with Manager(I):
Packit 562c7a
            async for i in Iterable():
Packit 562c7a
                I[0] += 1
Packit 562c7a
        I[0] += 1000
Packit 562c7a
Packit 562c7a
        async with Manager(I):
Packit 562c7a
            async for i in Iterable():
Packit 562c7a
                I[0] += 1
Packit 562c7a
        I[0] += 1000
Packit 562c7a
Packit 562c7a
    run_async(main())
Packit 562c7a
    print(I[0])
Packit 562c7a
Packit 562c7a
    ##############
Packit 562c7a
Packit 562c7a
    async def main():
Packit 562c7a
        async with Manager(I):
Packit 562c7a
            I[0] += 100
Packit 562c7a
            async for i in Iterable():
Packit 562c7a
                I[0] += 1
Packit 562c7a
            else:
Packit 562c7a
                I[0] += 10000000
Packit 562c7a
        I[0] += 1000
Packit 562c7a
Packit 562c7a
        async with Manager(I):
Packit 562c7a
            I[0] += 100
Packit 562c7a
            async for i in Iterable():
Packit 562c7a
                I[0] += 1
Packit 562c7a
            else:
Packit 562c7a
                I[0] += 10000000
Packit 562c7a
        I[0] += 1000
Packit 562c7a
Packit 562c7a
    run_async(main())
Packit 562c7a
    print(I[0])
Packit 562c7a
Packit 562c7a
Packit 562c7a
# old-style pre-3.5.2 AIter protocol - no longer supported
Packit 562c7a
#cdef class AI_old:
Packit 562c7a
#    async def __aiter__(self):
Packit 562c7a
#        1/0
Packit 562c7a
Packit 562c7a
Packit 562c7a
cdef class AI_new:
Packit 562c7a
    def __aiter__(self):
Packit 562c7a
        1/0
Packit 562c7a
Packit 562c7a
Packit 562c7a
def test_aiter_raises(AI):
Packit 562c7a
    """
Packit 562c7a
    #>>> test_aiter_raises(AI_old)
Packit 562c7a
    #RAISED
Packit 562c7a
    #0
Packit 562c7a
    >>> test_aiter_raises(AI_new)
Packit 562c7a
    RAISED
Packit 562c7a
    0
Packit 562c7a
    """
Packit 562c7a
    CNT = 0
Packit 562c7a
Packit 562c7a
    async def foo():
Packit 562c7a
        nonlocal CNT
Packit 562c7a
        async for i in AI():
Packit 562c7a
            CNT += 1
Packit 562c7a
        CNT += 10
Packit 562c7a
Packit 562c7a
    try:
Packit 562c7a
        run_async(foo())
Packit 562c7a
    except ZeroDivisionError:
Packit 562c7a
        print("RAISED")
Packit 562c7a
    else:
Packit 562c7a
        print("NOT RAISED")
Packit 562c7a
    return CNT