File: pytest_plugin.py

package info (click to toggle)
python-aiohttp 1.2.0-1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 2,288 kB
  • ctags: 4,380
  • sloc: python: 27,221; makefile: 236
file content (141 lines) | stat: -rw-r--r-- 3,757 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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
import asyncio
import contextlib

import pytest

from aiohttp.web import Application

from .test_utils import unused_port as _unused_port
from .test_utils import (RawTestServer, TestClient, TestServer, loop_context,
                         setup_test_loop, teardown_test_loop)


@contextlib.contextmanager
def _passthrough_loop_context(loop):
    if loop:
        # loop already exists, pass it straight through
        yield loop
    else:
        # this shadows loop_context's standard behavior
        loop = setup_test_loop()
        yield loop
        teardown_test_loop(loop)


def pytest_pycollect_makeitem(collector, name, obj):
    """
    Fix pytest collecting for coroutines.
    """
    if collector.funcnamefilter(name) and asyncio.iscoroutinefunction(obj):
        return list(collector._genfunctions(name, obj))


def pytest_pyfunc_call(pyfuncitem):
    """
    Run coroutines in an event loop instead of a normal function call.
    """
    if asyncio.iscoroutinefunction(pyfuncitem.function):
        existing_loop = pyfuncitem.funcargs.get('loop', None)
        with _passthrough_loop_context(existing_loop) as _loop:
            testargs = {arg: pyfuncitem.funcargs[arg]
                        for arg in pyfuncitem._fixtureinfo.argnames}

            task = _loop.create_task(pyfuncitem.obj(**testargs))
            _loop.run_until_complete(task)

        return True


@pytest.yield_fixture
def loop():
    with loop_context() as _loop:
        yield _loop


@pytest.fixture
def unused_port():
    return _unused_port


@pytest.yield_fixture
def test_server(loop):
    servers = []

    @asyncio.coroutine
    def go(app, **kwargs):
        assert app.loop is loop, \
            "Application is attached to other event loop"

        server = TestServer(app)
        yield from server.start_server(**kwargs)
        servers.append(server)
        return server

    yield go

    @asyncio.coroutine
    def finalize():
        while servers:
            yield from servers.pop().close()

    loop.run_until_complete(finalize())


@pytest.yield_fixture
def raw_test_server(loop):
    servers = []

    @asyncio.coroutine
    def go(handler, **kwargs):
        server = RawTestServer(handler, loop=loop)
        yield from server.start_server(**kwargs)
        servers.append(server)
        return server

    yield go

    @asyncio.coroutine
    def finalize():
        while servers:
            yield from servers.pop().close()

    loop.run_until_complete(finalize())


@pytest.yield_fixture
def test_client(loop):
    clients = []

    @asyncio.coroutine
    def go(__param, *args, **kwargs):
        if isinstance(__param, Application):
            assert not args, "args should be empty"
            assert __param.loop is loop, \
                "Application is attached to other event loop"
            client = TestClient(__param, **kwargs)
        elif isinstance(__param, TestServer):
            assert not args, "args should be empty"
            assert __param.app.loop is loop, \
                "TestServer is attached to other event loop"
            client = TestClient(__param, **kwargs)
        elif isinstance(__param, RawTestServer):
            assert not args, "args should be empty"
            assert __param._loop is loop, \
                "TestServer is attached to other event loop"
            client = TestClient(__param, **kwargs)
        else:
            __param = __param(loop, *args, **kwargs)
            client = TestClient(__param)

        yield from client.start_server()
        clients.append(client)
        return client

    yield go

    @asyncio.coroutine
    def finalize():
        while clients:
            yield from clients.pop().close()

    loop.run_until_complete(finalize())