File: test_generators_coroutines.py

package info (click to toggle)
python-makefun 1.15.4-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 440 kB
  • sloc: python: 2,384; makefile: 2
file content (119 lines) | stat: -rw-r--r-- 4,010 bytes parent folder | download
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
import sys

import pytest

from makefun import with_signature, create_function

try:
    from inspect import iscoroutinefunction
except ImportError:
    # let's assume there are no coroutine functions in old Python
    def iscoroutinefunction(f):
        return False

try:
    from inspect import isgeneratorfunction
except ImportError:
    # assume no generator function in old Python versions
    def isgeneratorfunction(f):
        return False


def test_generator():
    """ Tests that we can use a generator as function_handler in `create_function`"""

    # define the handler that should be called
    def my_generator_handler(b, a=0):
        for i in range(a, b):
            yield i * i

    # create the dynamic function
    dynamic_fun = create_function("foo(a, b)", my_generator_handler)

    assert isgeneratorfunction(dynamic_fun)

    assert list(dynamic_fun(1, 4)) == [1, 4, 9]


def test_generator_with_signature():
    """ Tests that we can write a generator and change its signature: it will still be a generator """

    @with_signature("foo(a)")
    def foo(*args, **kwargs):
        for i in range(1, 4):
            yield i * i

    assert isgeneratorfunction(foo)

    with pytest.raises(TypeError):
        foo()

    assert list(foo('dummy')) == [1, 4, 9]


def test_generator_based_coroutine():
    """ Tests that we can use a generator coroutine as function_handler in `create_function`"""

    # define the handler that should be called
    def my_gencoroutine_handler(first_msg):
        second_msg = (yield first_msg)
        yield second_msg

    # create the dynamic function
    dynamic_fun = create_function("foo(first_msg='hello')", my_gencoroutine_handler)

    # a legacy (generator-based) coroutine is not an asyncio coroutine..
    assert not iscoroutinefunction(dynamic_fun)
    assert isgeneratorfunction(dynamic_fun)

    cor = dynamic_fun('hi')
    first_result = next(cor)
    assert first_result == 'hi'
    second_result = cor.send('chaps')
    assert second_result == 'chaps'
    with pytest.raises(StopIteration):
        cor.send('ola')


@pytest.mark.skipif(sys.version_info < (3, 5), reason="native coroutines with async/await require python3.6 or higher")
def test_native_coroutine():
    """ Tests that we can use a native async coroutine as function_handler in `create_function`"""

    # define the handler that should be called
    from tests._test_py35 import make_native_coroutine_handler
    my_native_coroutine_handler = make_native_coroutine_handler()

    # create the dynamic function
    dynamic_fun = create_function("foo(sleep_time=2)", my_native_coroutine_handler)

    # check that this is a coroutine for inspect and for asyncio
    assert iscoroutinefunction(dynamic_fun)
    from asyncio import iscoroutinefunction as is_native_co
    assert is_native_co(dynamic_fun)

    # verify that the new function is a native coroutine and behaves correctly
    from asyncio import get_event_loop
    out = get_event_loop().run_until_complete(dynamic_fun(0.1))
    assert out == 0.1


@pytest.mark.skipif(sys.version_info < (3, 5), reason="native coroutines with async/await require python3.6 or higher")
def test_issue_96():
    """Same as `test_native_coroutine` but tests that we can use 'return' in the coroutine name"""

    # define the handler that should be called
    from tests._test_py35 import make_native_coroutine_handler
    my_native_coroutine_handler = make_native_coroutine_handler()

    # create the dynamic function
    dynamic_fun = create_function("foo_returns_bar(sleep_time=2)", my_native_coroutine_handler)

    # check that this is a coroutine for inspect and for asyncio
    assert iscoroutinefunction(dynamic_fun)
    from asyncio import iscoroutinefunction as is_native_co
    assert is_native_co(dynamic_fun)

    # verify that the new function is a native coroutine and behaves correctly
    from asyncio import get_event_loop
    out = get_event_loop().run_until_complete(dynamic_fun(0.1))
    assert out == 0.1