Path: blob/master/ invest-robot-contest_TinkoffBotTwitch-main/venv/lib/python3.8/site-packages/aiohttp/pytest_plugin.py
7756 views
import asyncio1import contextlib2import warnings3from collections.abc import Callable4from typing import Any, Awaitable, Callable, Dict, Generator, Optional, Union56import pytest78from aiohttp.helpers import PY_37, isasyncgenfunction9from aiohttp.web import Application1011from .test_utils import (12BaseTestServer,13RawTestServer,14TestClient,15TestServer,16loop_context,17setup_test_loop,18teardown_test_loop,19unused_port as _unused_port,20)2122try:23import uvloop24except ImportError: # pragma: no cover25uvloop = None2627try:28import tokio29except ImportError: # pragma: no cover30tokio = None3132AiohttpClient = Callable[[Union[Application, BaseTestServer]], Awaitable[TestClient]]333435def pytest_addoption(parser): # type: ignore[no-untyped-def]36parser.addoption(37"--aiohttp-fast",38action="store_true",39default=False,40help="run tests faster by disabling extra checks",41)42parser.addoption(43"--aiohttp-loop",44action="store",45default="pyloop",46help="run tests with specific loop: pyloop, uvloop, tokio or all",47)48parser.addoption(49"--aiohttp-enable-loop-debug",50action="store_true",51default=False,52help="enable event loop debug mode",53)545556def pytest_fixture_setup(fixturedef): # type: ignore[no-untyped-def]57"""Set up pytest fixture.5859Allow fixtures to be coroutines. Run coroutine fixtures in an event loop.60"""61func = fixturedef.func6263if isasyncgenfunction(func):64# async generator fixture65is_async_gen = True66elif asyncio.iscoroutinefunction(func):67# regular async fixture68is_async_gen = False69else:70# not an async fixture, nothing to do71return7273strip_request = False74if "request" not in fixturedef.argnames:75fixturedef.argnames += ("request",)76strip_request = True7778def wrapper(*args, **kwargs): # type: ignore[no-untyped-def]79request = kwargs["request"]80if strip_request:81del kwargs["request"]8283# if neither the fixture nor the test use the 'loop' fixture,84# 'getfixturevalue' will fail because the test is not parameterized85# (this can be removed someday if 'loop' is no longer parameterized)86if "loop" not in request.fixturenames:87raise Exception(88"Asynchronous fixtures must depend on the 'loop' fixture or "89"be used in tests depending from it."90)9192_loop = request.getfixturevalue("loop")9394if is_async_gen:95# for async generators, we need to advance the generator once,96# then advance it again in a finalizer97gen = func(*args, **kwargs)9899def finalizer(): # type: ignore[no-untyped-def]100try:101return _loop.run_until_complete(gen.__anext__())102except StopAsyncIteration:103pass104105request.addfinalizer(finalizer)106return _loop.run_until_complete(gen.__anext__())107else:108return _loop.run_until_complete(func(*args, **kwargs))109110fixturedef.func = wrapper111112113@pytest.fixture114def fast(request): # type: ignore[no-untyped-def]115"""--fast config option"""116return request.config.getoption("--aiohttp-fast")117118119@pytest.fixture120def loop_debug(request): # type: ignore[no-untyped-def]121"""--enable-loop-debug config option"""122return request.config.getoption("--aiohttp-enable-loop-debug")123124125@contextlib.contextmanager126def _runtime_warning_context(): # type: ignore[no-untyped-def]127"""Context manager which checks for RuntimeWarnings.128129This exists specifically to130avoid "coroutine 'X' was never awaited" warnings being missed.131132If RuntimeWarnings occur in the context a RuntimeError is raised.133"""134with warnings.catch_warnings(record=True) as _warnings:135yield136rw = [137"{w.filename}:{w.lineno}:{w.message}".format(w=w)138for w in _warnings139if w.category == RuntimeWarning140]141if rw:142raise RuntimeError(143"{} Runtime Warning{},\n{}".format(144len(rw), "" if len(rw) == 1 else "s", "\n".join(rw)145)146)147148149@contextlib.contextmanager150def _passthrough_loop_context(loop, fast=False): # type: ignore[no-untyped-def]151"""Passthrough loop context.152153Sets up and tears down a loop unless one is passed in via the loop154argument when it's passed straight through.155"""156if loop:157# loop already exists, pass it straight through158yield loop159else:160# this shadows loop_context's standard behavior161loop = setup_test_loop()162yield loop163teardown_test_loop(loop, fast=fast)164165166def pytest_pycollect_makeitem(collector, name, obj): # type: ignore[no-untyped-def]167"""Fix pytest collecting for coroutines."""168if collector.funcnamefilter(name) and asyncio.iscoroutinefunction(obj):169return list(collector._genfunctions(name, obj))170171172def pytest_pyfunc_call(pyfuncitem): # type: ignore[no-untyped-def]173"""Run coroutines in an event loop instead of a normal function call."""174fast = pyfuncitem.config.getoption("--aiohttp-fast")175if asyncio.iscoroutinefunction(pyfuncitem.function):176existing_loop = pyfuncitem.funcargs.get(177"proactor_loop"178) or pyfuncitem.funcargs.get("loop", None)179with _runtime_warning_context():180with _passthrough_loop_context(existing_loop, fast=fast) as _loop:181testargs = {182arg: pyfuncitem.funcargs[arg]183for arg in pyfuncitem._fixtureinfo.argnames184}185_loop.run_until_complete(pyfuncitem.obj(**testargs))186187return True188189190def pytest_generate_tests(metafunc): # type: ignore[no-untyped-def]191if "loop_factory" not in metafunc.fixturenames:192return193194loops = metafunc.config.option.aiohttp_loop195avail_factories = {"pyloop": asyncio.DefaultEventLoopPolicy}196197if uvloop is not None: # pragma: no cover198avail_factories["uvloop"] = uvloop.EventLoopPolicy199200if tokio is not None: # pragma: no cover201avail_factories["tokio"] = tokio.EventLoopPolicy202203if loops == "all":204loops = "pyloop,uvloop?,tokio?"205206factories = {} # type: ignore[var-annotated]207for name in loops.split(","):208required = not name.endswith("?")209name = name.strip(" ?")210if name not in avail_factories: # pragma: no cover211if required:212raise ValueError(213"Unknown loop '%s', available loops: %s"214% (name, list(factories.keys()))215)216else:217continue218factories[name] = avail_factories[name]219metafunc.parametrize(220"loop_factory", list(factories.values()), ids=list(factories.keys())221)222223224@pytest.fixture225def loop(loop_factory, fast, loop_debug): # type: ignore[no-untyped-def]226"""Return an instance of the event loop."""227policy = loop_factory()228asyncio.set_event_loop_policy(policy)229with loop_context(fast=fast) as _loop:230if loop_debug:231_loop.set_debug(True) # pragma: no cover232asyncio.set_event_loop(_loop)233yield _loop234235236@pytest.fixture237def proactor_loop(): # type: ignore[no-untyped-def]238if not PY_37:239policy = asyncio.get_event_loop_policy()240policy._loop_factory = asyncio.ProactorEventLoop # type: ignore[attr-defined]241else:242policy = asyncio.WindowsProactorEventLoopPolicy() # type: ignore[attr-defined]243asyncio.set_event_loop_policy(policy)244245with loop_context(policy.new_event_loop) as _loop:246asyncio.set_event_loop(_loop)247yield _loop248249250@pytest.fixture251def unused_port(aiohttp_unused_port): # type: ignore[no-untyped-def] # pragma: no cover252warnings.warn(253"Deprecated, use aiohttp_unused_port fixture instead",254DeprecationWarning,255stacklevel=2,256)257return aiohttp_unused_port258259260@pytest.fixture261def aiohttp_unused_port(): # type: ignore[no-untyped-def]262"""Return a port that is unused on the current host."""263return _unused_port264265266@pytest.fixture267def aiohttp_server(loop): # type: ignore[no-untyped-def]268"""Factory to create a TestServer instance, given an app.269270aiohttp_server(app, **kwargs)271"""272servers = []273274async def go(app, *, port=None, **kwargs): # type: ignore[no-untyped-def]275server = TestServer(app, port=port)276await server.start_server(loop=loop, **kwargs)277servers.append(server)278return server279280yield go281282async def finalize() -> None:283while servers:284await servers.pop().close()285286loop.run_until_complete(finalize())287288289@pytest.fixture290def test_server(aiohttp_server): # type: ignore[no-untyped-def] # pragma: no cover291warnings.warn(292"Deprecated, use aiohttp_server fixture instead",293DeprecationWarning,294stacklevel=2,295)296return aiohttp_server297298299@pytest.fixture300def aiohttp_raw_server(loop): # type: ignore[no-untyped-def]301"""Factory to create a RawTestServer instance, given a web handler.302303aiohttp_raw_server(handler, **kwargs)304"""305servers = []306307async def go(handler, *, port=None, **kwargs): # type: ignore[no-untyped-def]308server = RawTestServer(handler, port=port)309await server.start_server(loop=loop, **kwargs)310servers.append(server)311return server312313yield go314315async def finalize() -> None:316while servers:317await servers.pop().close()318319loop.run_until_complete(finalize())320321322@pytest.fixture323def raw_test_server( # type: ignore[no-untyped-def] # pragma: no cover324aiohttp_raw_server,325):326warnings.warn(327"Deprecated, use aiohttp_raw_server fixture instead",328DeprecationWarning,329stacklevel=2,330)331return aiohttp_raw_server332333334@pytest.fixture335def aiohttp_client(336loop: asyncio.AbstractEventLoop,337) -> Generator[AiohttpClient, None, None]:338"""Factory to create a TestClient instance.339340aiohttp_client(app, **kwargs)341aiohttp_client(server, **kwargs)342aiohttp_client(raw_server, **kwargs)343"""344clients = []345346async def go(347__param: Union[Application, BaseTestServer],348*args: Any,349server_kwargs: Optional[Dict[str, Any]] = None,350**kwargs: Any351) -> TestClient:352353if isinstance(__param, Callable) and not isinstance( # type: ignore[arg-type]354__param, (Application, BaseTestServer)355):356__param = __param(loop, *args, **kwargs)357kwargs = {}358else:359assert not args, "args should be empty"360361if isinstance(__param, Application):362server_kwargs = server_kwargs or {}363server = TestServer(__param, loop=loop, **server_kwargs)364client = TestClient(server, loop=loop, **kwargs)365elif isinstance(__param, BaseTestServer):366client = TestClient(__param, loop=loop, **kwargs)367else:368raise ValueError("Unknown argument type: %r" % type(__param))369370await client.start_server()371clients.append(client)372return client373374yield go375376async def finalize() -> None:377while clients:378await clients.pop().close()379380loop.run_until_complete(finalize())381382383@pytest.fixture384def test_client(aiohttp_client): # type: ignore[no-untyped-def] # pragma: no cover385warnings.warn(386"Deprecated, use aiohttp_client fixture instead",387DeprecationWarning,388stacklevel=2,389)390return aiohttp_client391392393