From 06adcba97bfff18d0d6e2cafeb4228cfbd99f8b3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 15 Apr 2026 20:52:01 +0000 Subject: [PATCH 1/6] Initial plan From 988de768745de826851f437cf8efbb1530f4849b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 15 Apr 2026 21:02:33 +0000 Subject: [PATCH 2/6] chore: prepare pytest-asyncio uvloop hook migration Agent-Logs-Url: https://github.com/plugboard-dev/plugboard/sessions/97ae65cc-0c75-4da6-83fa-22fbc21aa4d6 Co-authored-by: toby-coleman <13170610+toby-coleman@users.noreply.github.com> --- tests/conftest.py | 28 +++++++++++++++++++++++----- tests/unit/test_conftest.py | 16 ++++++++++++++++ 2 files changed, 39 insertions(+), 5 deletions(-) create mode 100644 tests/unit/test_conftest.py diff --git a/tests/conftest.py b/tests/conftest.py index b7688fcb..6e4e1f9a 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,7 +1,7 @@ """Configuration for the test suite.""" from abc import ABC -from asyncio.events import BaseDefaultEventLoopPolicy +import asyncio import multiprocessing import os import typing as _t @@ -22,10 +22,28 @@ from plugboard.utils.settings import Settings -@pytest.fixture(scope="session") -def event_loop_policy() -> BaseDefaultEventLoopPolicy: - """Set uvloop as the event loop policy for the test session.""" - return uvloop.EventLoopPolicy() +_SUPPORTS_PYTEST_ASYNCIO_LOOP_FACTORIES = hasattr( + getattr(pytest_asyncio, "plugin", None), + "PytestAsyncioSpecs", +) + + +@pytest.hookimpl(optionalhook=True) +def pytest_asyncio_loop_factories( + config: pytest.Config, + item: pytest.Item, +) -> dict[str, _t.Callable[[], asyncio.AbstractEventLoop]]: + """Configure pytest-asyncio to create event loops with uvloop.""" + del config, item + return {"uvloop": uvloop.new_event_loop} + + +if not _SUPPORTS_PYTEST_ASYNCIO_LOOP_FACTORIES: + + @pytest.fixture(scope="session") + def event_loop_policy() -> _t.Any: + """Fallback uvloop policy for pytest-asyncio versions without hook support.""" + return uvloop.EventLoopPolicy() @pytest.fixture(scope="session", autouse=True) diff --git a/tests/unit/test_conftest.py b/tests/unit/test_conftest.py new file mode 100644 index 00000000..0d6c2493 --- /dev/null +++ b/tests/unit/test_conftest.py @@ -0,0 +1,16 @@ +"""Unit tests for the shared pytest configuration.""" + +import typing as _t + +import pytest +import uvloop + +from tests import conftest + + +def test_pytest_asyncio_loop_factories_uses_uvloop() -> None: + """The shared pytest-asyncio hook should configure uvloop factories.""" + assert conftest.pytest_asyncio_loop_factories( + _t.cast(pytest.Config, None), + _t.cast(pytest.Item, None), + ) == {"uvloop": uvloop.new_event_loop} From 63c3691daea07fdef52341647c28dac958128d11 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 15 Apr 2026 21:04:44 +0000 Subject: [PATCH 3/6] chore: polish uvloop pytest-asyncio migration Agent-Logs-Url: https://github.com/plugboard-dev/plugboard/sessions/97ae65cc-0c75-4da6-83fa-22fbc21aa4d6 Co-authored-by: toby-coleman <13170610+toby-coleman@users.noreply.github.com> --- tests/conftest.py | 4 ++-- tests/unit/test_conftest.py | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 6e4e1f9a..2916b73a 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -22,7 +22,7 @@ from plugboard.utils.settings import Settings -_SUPPORTS_PYTEST_ASYNCIO_LOOP_FACTORIES = hasattr( +_PYTEST_ASYNCIO_SUPPORTS_LOOP_FACTORIES = hasattr( getattr(pytest_asyncio, "plugin", None), "PytestAsyncioSpecs", ) @@ -38,7 +38,7 @@ def pytest_asyncio_loop_factories( return {"uvloop": uvloop.new_event_loop} -if not _SUPPORTS_PYTEST_ASYNCIO_LOOP_FACTORIES: +if not _PYTEST_ASYNCIO_SUPPORTS_LOOP_FACTORIES: @pytest.fixture(scope="session") def event_loop_policy() -> _t.Any: diff --git a/tests/unit/test_conftest.py b/tests/unit/test_conftest.py index 0d6c2493..238b4eb9 100644 --- a/tests/unit/test_conftest.py +++ b/tests/unit/test_conftest.py @@ -1,6 +1,6 @@ """Unit tests for the shared pytest configuration.""" -import typing as _t +from unittest.mock import MagicMock import pytest import uvloop @@ -11,6 +11,6 @@ def test_pytest_asyncio_loop_factories_uses_uvloop() -> None: """The shared pytest-asyncio hook should configure uvloop factories.""" assert conftest.pytest_asyncio_loop_factories( - _t.cast(pytest.Config, None), - _t.cast(pytest.Item, None), + MagicMock(spec=pytest.Config), + MagicMock(spec=pytest.Item), ) == {"uvloop": uvloop.new_event_loop} From 49447b9e76e36bc84f54b06a7f1288c3915e1c26 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 15 Apr 2026 21:06:26 +0000 Subject: [PATCH 4/6] chore: finalize uvloop pytest-asyncio compatibility Agent-Logs-Url: https://github.com/plugboard-dev/plugboard/sessions/97ae65cc-0c75-4da6-83fa-22fbc21aa4d6 Co-authored-by: toby-coleman <13170610+toby-coleman@users.noreply.github.com> --- tests/conftest.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 2916b73a..d9549769 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -22,7 +22,7 @@ from plugboard.utils.settings import Settings -_PYTEST_ASYNCIO_SUPPORTS_LOOP_FACTORIES = hasattr( +_PYTEST_ASYNCIO_SUPPORTS_LOOP_FACTORY_HOOK = hasattr( getattr(pytest_asyncio, "plugin", None), "PytestAsyncioSpecs", ) @@ -38,10 +38,10 @@ def pytest_asyncio_loop_factories( return {"uvloop": uvloop.new_event_loop} -if not _PYTEST_ASYNCIO_SUPPORTS_LOOP_FACTORIES: +if not _PYTEST_ASYNCIO_SUPPORTS_LOOP_FACTORY_HOOK: @pytest.fixture(scope="session") - def event_loop_policy() -> _t.Any: + def event_loop_policy() -> uvloop.EventLoopPolicy: """Fallback uvloop policy for pytest-asyncio versions without hook support.""" return uvloop.EventLoopPolicy() From 7d7d723ab8d0b9865f9e7d68e8e3c420a9f37bbe Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 15 Apr 2026 21:08:42 +0000 Subject: [PATCH 5/6] chore: cover pytest-asyncio uvloop fallback Agent-Logs-Url: https://github.com/plugboard-dev/plugboard/sessions/97ae65cc-0c75-4da6-83fa-22fbc21aa4d6 Co-authored-by: toby-coleman <13170610+toby-coleman@users.noreply.github.com> --- tests/conftest.py | 4 ++-- tests/unit/test_conftest.py | 10 ++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index d9549769..c27ceee5 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -22,7 +22,7 @@ from plugboard.utils.settings import Settings -_PYTEST_ASYNCIO_SUPPORTS_LOOP_FACTORY_HOOK = hasattr( +_HAS_LOOP_FACTORY_HOOK = hasattr( getattr(pytest_asyncio, "plugin", None), "PytestAsyncioSpecs", ) @@ -38,7 +38,7 @@ def pytest_asyncio_loop_factories( return {"uvloop": uvloop.new_event_loop} -if not _PYTEST_ASYNCIO_SUPPORTS_LOOP_FACTORY_HOOK: +if not _HAS_LOOP_FACTORY_HOOK: @pytest.fixture(scope="session") def event_loop_policy() -> uvloop.EventLoopPolicy: diff --git a/tests/unit/test_conftest.py b/tests/unit/test_conftest.py index 238b4eb9..b8e4e38b 100644 --- a/tests/unit/test_conftest.py +++ b/tests/unit/test_conftest.py @@ -1,5 +1,6 @@ """Unit tests for the shared pytest configuration.""" +import typing as _t from unittest.mock import MagicMock import pytest @@ -14,3 +15,12 @@ def test_pytest_asyncio_loop_factories_uses_uvloop() -> None: MagicMock(spec=pytest.Config), MagicMock(spec=pytest.Item), ) == {"uvloop": uvloop.new_event_loop} + + +def test_event_loop_policy_fallback_uses_uvloop() -> None: + """Older pytest-asyncio releases should still get uvloop via the fallback fixture.""" + if conftest._HAS_LOOP_FACTORY_HOOK: + pytest.skip("Installed pytest-asyncio already provides the loop-factory hook") + + event_loop_policy = _t.cast(_t.Any, conftest.event_loop_policy) + assert isinstance(event_loop_policy.__wrapped__(), uvloop.EventLoopPolicy) From 8f536ba0473b4eb12eb176bbe28c84e912296ba4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 23 Apr 2026 18:45:01 +0000 Subject: [PATCH 6/6] chore: simplify pytest-asyncio uvloop hook Agent-Logs-Url: https://github.com/plugboard-dev/plugboard/sessions/1dcc6e9b-2a3e-46e1-9493-f1dd0572e763 Co-authored-by: toby-coleman <13170610+toby-coleman@users.noreply.github.com> --- tests/conftest.py | 20 +------------------- tests/unit/test_conftest.py | 18 +----------------- 2 files changed, 2 insertions(+), 36 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 20af10be..7513a8ab 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -21,30 +21,12 @@ from plugboard.utils.settings import Settings -_HAS_LOOP_FACTORY_HOOK = hasattr( - getattr(pytest_asyncio, "plugin", None), - "PytestAsyncioSpecs", -) - - @pytest.hookimpl(optionalhook=True) -def pytest_asyncio_loop_factories( - config: pytest.Config, - item: pytest.Item, -) -> dict[str, _t.Callable[[], asyncio.AbstractEventLoop]]: +def pytest_asyncio_loop_factories() -> dict[str, _t.Callable[[], asyncio.AbstractEventLoop]]: """Configure pytest-asyncio to create event loops with uvloop.""" - del config, item return {"uvloop": uvloop.new_event_loop} -if not _HAS_LOOP_FACTORY_HOOK: - - @pytest.fixture(scope="session") - def event_loop_policy() -> uvloop.EventLoopPolicy: - """Fallback uvloop policy for pytest-asyncio versions without hook support.""" - return uvloop.EventLoopPolicy() - - @pytest.fixture(scope="session", autouse=True) def mp_set_start_method() -> None: """Set the start method for multiprocessing to 'spawn'.""" diff --git a/tests/unit/test_conftest.py b/tests/unit/test_conftest.py index b8e4e38b..3b83e61d 100644 --- a/tests/unit/test_conftest.py +++ b/tests/unit/test_conftest.py @@ -1,9 +1,5 @@ """Unit tests for the shared pytest configuration.""" -import typing as _t -from unittest.mock import MagicMock - -import pytest import uvloop from tests import conftest @@ -11,16 +7,4 @@ def test_pytest_asyncio_loop_factories_uses_uvloop() -> None: """The shared pytest-asyncio hook should configure uvloop factories.""" - assert conftest.pytest_asyncio_loop_factories( - MagicMock(spec=pytest.Config), - MagicMock(spec=pytest.Item), - ) == {"uvloop": uvloop.new_event_loop} - - -def test_event_loop_policy_fallback_uses_uvloop() -> None: - """Older pytest-asyncio releases should still get uvloop via the fallback fixture.""" - if conftest._HAS_LOOP_FACTORY_HOOK: - pytest.skip("Installed pytest-asyncio already provides the loop-factory hook") - - event_loop_policy = _t.cast(_t.Any, conftest.event_loop_policy) - assert isinstance(event_loop_policy.__wrapped__(), uvloop.EventLoopPolicy) + assert conftest.pytest_asyncio_loop_factories() == {"uvloop": uvloop.new_event_loop}