mirror of
https://github.com/cockpit-project/cockpit.git
synced 2026-11-03 21:49:50 -09:00
pytests: update fixtures to not use deprecated event_loop
pytest_asyncio dropped `event_loop` fixture in version 1.0.0
This commit is contained in:
parent
fbdc5a89e7
commit
d53b3e8400
7 changed files with 49 additions and 22 deletions
|
|
@ -221,7 +221,7 @@ deps =
|
|||
lint: ruff
|
||||
lint: vulture
|
||||
pytest
|
||||
pytest-asyncio < 1.0
|
||||
pytest-asyncio
|
||||
pytest: pytest-cov
|
||||
pytest: pytest-timeout
|
||||
pytest: pytest-xdist
|
||||
|
|
|
|||
|
|
@ -2,9 +2,10 @@ import asyncio
|
|||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
from typing import Iterable
|
||||
from typing import Any, AsyncGenerator, Iterable
|
||||
|
||||
import pytest
|
||||
import pytest_asyncio
|
||||
|
||||
from cockpit import polyfills
|
||||
from cockpit._vendor.systemd_ctypes import EventLoopPolicy
|
||||
|
|
@ -18,6 +19,14 @@ except (ImportError, AttributeError):
|
|||
# old versions don't have __version_tuple__ or event_loop_policy
|
||||
have_event_loop_policy_fixture = False
|
||||
|
||||
# pytest fixture polyfill
|
||||
# pytest_asyncio.fixture() was added in 0.22.0
|
||||
if not hasattr(pytest_asyncio, 'fixture'):
|
||||
# mypy is strict here because of slightly different signatures.
|
||||
# On old versions of pytest_asyncio this is fine to do as `pytest.fixture`
|
||||
# was always used before `pytest_asyncio.fixture` existed.
|
||||
pytest_asyncio.fixture = pytest.fixture # type: ignore[assignment]
|
||||
|
||||
|
||||
def any_subprocesses() -> bool:
|
||||
# Make sure we don't leak subprocesses
|
||||
|
|
@ -67,18 +76,32 @@ else:
|
|||
return EventLoopPolicy()
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def _check_settled(event_loop) -> Iterable[None]:
|
||||
def filter_current_task(tasks: 'set[asyncio.Task[Any]]',
|
||||
current_task: 'asyncio.Task[Any]') -> 'set[asyncio.Task[Any]]':
|
||||
return {task for task in tasks if task is not current_task}
|
||||
|
||||
|
||||
@pytest_asyncio.fixture(autouse=True)
|
||||
async def _check_settled() -> AsyncGenerator[None, None]:
|
||||
yield
|
||||
|
||||
# python 3.6 asyncio does not have 'current_task' attribute
|
||||
if hasattr(asyncio, 'current_task'):
|
||||
current_task = asyncio.current_task()
|
||||
else:
|
||||
current_task = asyncio.Task.current_task() # type: ignore[attr-defined]
|
||||
assert current_task is not None
|
||||
event_loop = asyncio.get_running_loop()
|
||||
|
||||
# Let all tasks and subprocesses run to completion
|
||||
for _ in range(200):
|
||||
if not (asyncio.all_tasks(event_loop) or any_subprocesses()):
|
||||
all_tasks = filter_current_task(asyncio.all_tasks(loop=event_loop), current_task)
|
||||
if not (all_tasks or any_subprocesses()):
|
||||
break
|
||||
event_loop.run_until_complete(asyncio.sleep(0.005))
|
||||
await asyncio.sleep(0.005)
|
||||
|
||||
# No tasks left
|
||||
assert asyncio.all_tasks(loop=event_loop) == set()
|
||||
assert filter_current_task(asyncio.all_tasks(loop=event_loop), current_task) == set()
|
||||
|
||||
# No subprocesses left
|
||||
if any_subprocesses():
|
||||
|
|
|
|||
|
|
@ -92,13 +92,12 @@ class MockTransport(asyncio.Transport):
|
|||
_, channel, data = data.split(b'\n', 2)
|
||||
self.queue.put_nowait((channel.decode('ascii'), data))
|
||||
|
||||
def stop(self, event_loop: Optional[asyncio.AbstractEventLoop] = None) -> None:
|
||||
async def stop(self) -> None:
|
||||
keep_open = self.protocol.eof_received()
|
||||
if keep_open:
|
||||
assert event_loop is not None
|
||||
self.close_future = event_loop.create_future()
|
||||
self.close_future = asyncio.get_running_loop().create_future()
|
||||
try:
|
||||
event_loop.run_until_complete(self.close_future)
|
||||
await self.close_future
|
||||
finally:
|
||||
self.close_future = None
|
||||
|
||||
|
|
|
|||
|
|
@ -14,9 +14,10 @@ import sys
|
|||
import unittest.mock
|
||||
from collections import deque
|
||||
from pathlib import Path
|
||||
from typing import Dict, Generator, Iterable, Iterator, Sequence, Union
|
||||
from typing import AsyncGenerator, Dict, Generator, Iterator, Sequence, Union
|
||||
|
||||
import pytest
|
||||
import pytest_asyncio
|
||||
|
||||
from cockpit._vendor.systemd_ctypes import bus
|
||||
from cockpit.bridge import Bridge
|
||||
|
|
@ -67,13 +68,13 @@ def add_pseudo(bridge: Bridge) -> None:
|
|||
])
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def no_init_transport(event_loop: asyncio.AbstractEventLoop, bridge: Bridge) -> Iterable[MockTransport]:
|
||||
@pytest_asyncio.fixture()
|
||||
async def no_init_transport(bridge: Bridge) -> AsyncGenerator[MockTransport, None]:
|
||||
transport = MockTransport(bridge)
|
||||
try:
|
||||
yield transport
|
||||
finally:
|
||||
transport.stop(event_loop)
|
||||
await transport.stop()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
import argparse
|
||||
import asyncio
|
||||
import datetime
|
||||
import json
|
||||
import sys
|
||||
import time
|
||||
from typing import Iterable
|
||||
from typing import AsyncGenerator
|
||||
|
||||
import pytest
|
||||
import pytest_asyncio
|
||||
|
||||
# Skip import when PCP is not available (for example in our tox env without system packages)
|
||||
try:
|
||||
|
|
@ -31,14 +31,14 @@ from cockpit.bridge import Bridge
|
|||
from .mocktransport import MockTransport
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def no_init_transport(event_loop: asyncio.AbstractEventLoop) -> Iterable[MockTransport]:
|
||||
@pytest_asyncio.fixture()
|
||||
async def no_init_transport() -> AsyncGenerator[MockTransport, None]:
|
||||
bridge = Bridge(argparse.Namespace(privileged=False, beipack=False))
|
||||
transport = MockTransport(bridge)
|
||||
try:
|
||||
yield transport
|
||||
finally:
|
||||
transport.stop(event_loop)
|
||||
await transport.stop()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import sys
|
|||
import time
|
||||
|
||||
import pytest
|
||||
import pytest_asyncio
|
||||
|
||||
from cockpit.channel import ChannelError
|
||||
from cockpit.packages import BridgeConfig
|
||||
|
|
@ -38,8 +39,9 @@ def bridge():
|
|||
return Bridge()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def transport(bridge):
|
||||
# requires an event loop for queue in MockTransport
|
||||
@pytest_asyncio.fixture()
|
||||
async def transport(bridge): # noqa: RUF029
|
||||
return MockTransport(bridge)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import pytest
|
||||
|
||||
pytest.Module._obj # type: ignore[attr-defined]
|
||||
|
||||
pytest.Module._check_settled # type: ignore[attr-defined]
|
||||
|
|
|
|||
Loading…
Reference in a new issue