Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wiseplat
GitHub Repository: wiseplat/python-code
Path: blob/master/ invest-robot-contest_TinkoffBotTwitch-main/venv/lib/python3.8/site-packages/aiohttp/pytest_plugin.py
7756 views
1
import asyncio
2
import contextlib
3
import warnings
4
from collections.abc import Callable
5
from typing import Any, Awaitable, Callable, Dict, Generator, Optional, Union
6
7
import pytest
8
9
from aiohttp.helpers import PY_37, isasyncgenfunction
10
from aiohttp.web import Application
11
12
from .test_utils import (
13
BaseTestServer,
14
RawTestServer,
15
TestClient,
16
TestServer,
17
loop_context,
18
setup_test_loop,
19
teardown_test_loop,
20
unused_port as _unused_port,
21
)
22
23
try:
24
import uvloop
25
except ImportError: # pragma: no cover
26
uvloop = None
27
28
try:
29
import tokio
30
except ImportError: # pragma: no cover
31
tokio = None
32
33
AiohttpClient = Callable[[Union[Application, BaseTestServer]], Awaitable[TestClient]]
34
35
36
def pytest_addoption(parser): # type: ignore[no-untyped-def]
37
parser.addoption(
38
"--aiohttp-fast",
39
action="store_true",
40
default=False,
41
help="run tests faster by disabling extra checks",
42
)
43
parser.addoption(
44
"--aiohttp-loop",
45
action="store",
46
default="pyloop",
47
help="run tests with specific loop: pyloop, uvloop, tokio or all",
48
)
49
parser.addoption(
50
"--aiohttp-enable-loop-debug",
51
action="store_true",
52
default=False,
53
help="enable event loop debug mode",
54
)
55
56
57
def pytest_fixture_setup(fixturedef): # type: ignore[no-untyped-def]
58
"""Set up pytest fixture.
59
60
Allow fixtures to be coroutines. Run coroutine fixtures in an event loop.
61
"""
62
func = fixturedef.func
63
64
if isasyncgenfunction(func):
65
# async generator fixture
66
is_async_gen = True
67
elif asyncio.iscoroutinefunction(func):
68
# regular async fixture
69
is_async_gen = False
70
else:
71
# not an async fixture, nothing to do
72
return
73
74
strip_request = False
75
if "request" not in fixturedef.argnames:
76
fixturedef.argnames += ("request",)
77
strip_request = True
78
79
def wrapper(*args, **kwargs): # type: ignore[no-untyped-def]
80
request = kwargs["request"]
81
if strip_request:
82
del kwargs["request"]
83
84
# if neither the fixture nor the test use the 'loop' fixture,
85
# 'getfixturevalue' will fail because the test is not parameterized
86
# (this can be removed someday if 'loop' is no longer parameterized)
87
if "loop" not in request.fixturenames:
88
raise Exception(
89
"Asynchronous fixtures must depend on the 'loop' fixture or "
90
"be used in tests depending from it."
91
)
92
93
_loop = request.getfixturevalue("loop")
94
95
if is_async_gen:
96
# for async generators, we need to advance the generator once,
97
# then advance it again in a finalizer
98
gen = func(*args, **kwargs)
99
100
def finalizer(): # type: ignore[no-untyped-def]
101
try:
102
return _loop.run_until_complete(gen.__anext__())
103
except StopAsyncIteration:
104
pass
105
106
request.addfinalizer(finalizer)
107
return _loop.run_until_complete(gen.__anext__())
108
else:
109
return _loop.run_until_complete(func(*args, **kwargs))
110
111
fixturedef.func = wrapper
112
113
114
@pytest.fixture
115
def fast(request): # type: ignore[no-untyped-def]
116
"""--fast config option"""
117
return request.config.getoption("--aiohttp-fast")
118
119
120
@pytest.fixture
121
def loop_debug(request): # type: ignore[no-untyped-def]
122
"""--enable-loop-debug config option"""
123
return request.config.getoption("--aiohttp-enable-loop-debug")
124
125
126
@contextlib.contextmanager
127
def _runtime_warning_context(): # type: ignore[no-untyped-def]
128
"""Context manager which checks for RuntimeWarnings.
129
130
This exists specifically to
131
avoid "coroutine 'X' was never awaited" warnings being missed.
132
133
If RuntimeWarnings occur in the context a RuntimeError is raised.
134
"""
135
with warnings.catch_warnings(record=True) as _warnings:
136
yield
137
rw = [
138
"{w.filename}:{w.lineno}:{w.message}".format(w=w)
139
for w in _warnings
140
if w.category == RuntimeWarning
141
]
142
if rw:
143
raise RuntimeError(
144
"{} Runtime Warning{},\n{}".format(
145
len(rw), "" if len(rw) == 1 else "s", "\n".join(rw)
146
)
147
)
148
149
150
@contextlib.contextmanager
151
def _passthrough_loop_context(loop, fast=False): # type: ignore[no-untyped-def]
152
"""Passthrough loop context.
153
154
Sets up and tears down a loop unless one is passed in via the loop
155
argument when it's passed straight through.
156
"""
157
if loop:
158
# loop already exists, pass it straight through
159
yield loop
160
else:
161
# this shadows loop_context's standard behavior
162
loop = setup_test_loop()
163
yield loop
164
teardown_test_loop(loop, fast=fast)
165
166
167
def pytest_pycollect_makeitem(collector, name, obj): # type: ignore[no-untyped-def]
168
"""Fix pytest collecting for coroutines."""
169
if collector.funcnamefilter(name) and asyncio.iscoroutinefunction(obj):
170
return list(collector._genfunctions(name, obj))
171
172
173
def pytest_pyfunc_call(pyfuncitem): # type: ignore[no-untyped-def]
174
"""Run coroutines in an event loop instead of a normal function call."""
175
fast = pyfuncitem.config.getoption("--aiohttp-fast")
176
if asyncio.iscoroutinefunction(pyfuncitem.function):
177
existing_loop = pyfuncitem.funcargs.get(
178
"proactor_loop"
179
) or pyfuncitem.funcargs.get("loop", None)
180
with _runtime_warning_context():
181
with _passthrough_loop_context(existing_loop, fast=fast) as _loop:
182
testargs = {
183
arg: pyfuncitem.funcargs[arg]
184
for arg in pyfuncitem._fixtureinfo.argnames
185
}
186
_loop.run_until_complete(pyfuncitem.obj(**testargs))
187
188
return True
189
190
191
def pytest_generate_tests(metafunc): # type: ignore[no-untyped-def]
192
if "loop_factory" not in metafunc.fixturenames:
193
return
194
195
loops = metafunc.config.option.aiohttp_loop
196
avail_factories = {"pyloop": asyncio.DefaultEventLoopPolicy}
197
198
if uvloop is not None: # pragma: no cover
199
avail_factories["uvloop"] = uvloop.EventLoopPolicy
200
201
if tokio is not None: # pragma: no cover
202
avail_factories["tokio"] = tokio.EventLoopPolicy
203
204
if loops == "all":
205
loops = "pyloop,uvloop?,tokio?"
206
207
factories = {} # type: ignore[var-annotated]
208
for name in loops.split(","):
209
required = not name.endswith("?")
210
name = name.strip(" ?")
211
if name not in avail_factories: # pragma: no cover
212
if required:
213
raise ValueError(
214
"Unknown loop '%s', available loops: %s"
215
% (name, list(factories.keys()))
216
)
217
else:
218
continue
219
factories[name] = avail_factories[name]
220
metafunc.parametrize(
221
"loop_factory", list(factories.values()), ids=list(factories.keys())
222
)
223
224
225
@pytest.fixture
226
def loop(loop_factory, fast, loop_debug): # type: ignore[no-untyped-def]
227
"""Return an instance of the event loop."""
228
policy = loop_factory()
229
asyncio.set_event_loop_policy(policy)
230
with loop_context(fast=fast) as _loop:
231
if loop_debug:
232
_loop.set_debug(True) # pragma: no cover
233
asyncio.set_event_loop(_loop)
234
yield _loop
235
236
237
@pytest.fixture
238
def proactor_loop(): # type: ignore[no-untyped-def]
239
if not PY_37:
240
policy = asyncio.get_event_loop_policy()
241
policy._loop_factory = asyncio.ProactorEventLoop # type: ignore[attr-defined]
242
else:
243
policy = asyncio.WindowsProactorEventLoopPolicy() # type: ignore[attr-defined]
244
asyncio.set_event_loop_policy(policy)
245
246
with loop_context(policy.new_event_loop) as _loop:
247
asyncio.set_event_loop(_loop)
248
yield _loop
249
250
251
@pytest.fixture
252
def unused_port(aiohttp_unused_port): # type: ignore[no-untyped-def] # pragma: no cover
253
warnings.warn(
254
"Deprecated, use aiohttp_unused_port fixture instead",
255
DeprecationWarning,
256
stacklevel=2,
257
)
258
return aiohttp_unused_port
259
260
261
@pytest.fixture
262
def aiohttp_unused_port(): # type: ignore[no-untyped-def]
263
"""Return a port that is unused on the current host."""
264
return _unused_port
265
266
267
@pytest.fixture
268
def aiohttp_server(loop): # type: ignore[no-untyped-def]
269
"""Factory to create a TestServer instance, given an app.
270
271
aiohttp_server(app, **kwargs)
272
"""
273
servers = []
274
275
async def go(app, *, port=None, **kwargs): # type: ignore[no-untyped-def]
276
server = TestServer(app, port=port)
277
await server.start_server(loop=loop, **kwargs)
278
servers.append(server)
279
return server
280
281
yield go
282
283
async def finalize() -> None:
284
while servers:
285
await servers.pop().close()
286
287
loop.run_until_complete(finalize())
288
289
290
@pytest.fixture
291
def test_server(aiohttp_server): # type: ignore[no-untyped-def] # pragma: no cover
292
warnings.warn(
293
"Deprecated, use aiohttp_server fixture instead",
294
DeprecationWarning,
295
stacklevel=2,
296
)
297
return aiohttp_server
298
299
300
@pytest.fixture
301
def aiohttp_raw_server(loop): # type: ignore[no-untyped-def]
302
"""Factory to create a RawTestServer instance, given a web handler.
303
304
aiohttp_raw_server(handler, **kwargs)
305
"""
306
servers = []
307
308
async def go(handler, *, port=None, **kwargs): # type: ignore[no-untyped-def]
309
server = RawTestServer(handler, port=port)
310
await server.start_server(loop=loop, **kwargs)
311
servers.append(server)
312
return server
313
314
yield go
315
316
async def finalize() -> None:
317
while servers:
318
await servers.pop().close()
319
320
loop.run_until_complete(finalize())
321
322
323
@pytest.fixture
324
def raw_test_server( # type: ignore[no-untyped-def] # pragma: no cover
325
aiohttp_raw_server,
326
):
327
warnings.warn(
328
"Deprecated, use aiohttp_raw_server fixture instead",
329
DeprecationWarning,
330
stacklevel=2,
331
)
332
return aiohttp_raw_server
333
334
335
@pytest.fixture
336
def aiohttp_client(
337
loop: asyncio.AbstractEventLoop,
338
) -> Generator[AiohttpClient, None, None]:
339
"""Factory to create a TestClient instance.
340
341
aiohttp_client(app, **kwargs)
342
aiohttp_client(server, **kwargs)
343
aiohttp_client(raw_server, **kwargs)
344
"""
345
clients = []
346
347
async def go(
348
__param: Union[Application, BaseTestServer],
349
*args: Any,
350
server_kwargs: Optional[Dict[str, Any]] = None,
351
**kwargs: Any
352
) -> TestClient:
353
354
if isinstance(__param, Callable) and not isinstance( # type: ignore[arg-type]
355
__param, (Application, BaseTestServer)
356
):
357
__param = __param(loop, *args, **kwargs)
358
kwargs = {}
359
else:
360
assert not args, "args should be empty"
361
362
if isinstance(__param, Application):
363
server_kwargs = server_kwargs or {}
364
server = TestServer(__param, loop=loop, **server_kwargs)
365
client = TestClient(server, loop=loop, **kwargs)
366
elif isinstance(__param, BaseTestServer):
367
client = TestClient(__param, loop=loop, **kwargs)
368
else:
369
raise ValueError("Unknown argument type: %r" % type(__param))
370
371
await client.start_server()
372
clients.append(client)
373
return client
374
375
yield go
376
377
async def finalize() -> None:
378
while clients:
379
await clients.pop().close()
380
381
loop.run_until_complete(finalize())
382
383
384
@pytest.fixture
385
def test_client(aiohttp_client): # type: ignore[no-untyped-def] # pragma: no cover
386
warnings.warn(
387
"Deprecated, use aiohttp_client fixture instead",
388
DeprecationWarning,
389
stacklevel=2,
390
)
391
return aiohttp_client
392
393