From 6bc9268dc8e359b7834622fb94ed633e418f7cbd Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 9 Mar 2024 22:05:54 +0200 Subject: [PATCH 1/4] Use `FixtureRequest` instead of `SubRequest` `SubRequest` is a subclass of `FixtureRequest`, but is currently private so pytest-asyncio uses `Any` instead. However, `FixtureRequest` typing is sufficient for our needs, so can use that instead. --- pytest_asyncio/plugin.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/pytest_asyncio/plugin.py b/pytest_asyncio/plugin.py index 36066cf2..5bfb234e 100644 --- a/pytest_asyncio/plugin.py +++ b/pytest_asyncio/plugin.py @@ -64,7 +64,6 @@ # https://github.com/pytest-dev/pytest/pull/9510 FixtureDef = Any -SubRequest = Any class PytestAsyncioError(Exception): @@ -282,7 +281,7 @@ def _add_kwargs( kwargs: Dict[str, Any], event_loop_fixture_id: str, event_loop: asyncio.AbstractEventLoop, - request: SubRequest, + request: FixtureRequest, ) -> Dict[str, Any]: sig = inspect.signature(func) ret = kwargs.copy() @@ -316,7 +315,7 @@ def _wrap_asyncgen_fixture(fixturedef: FixtureDef, event_loop_fixture_id: str) - fixture = fixturedef.func @functools.wraps(fixture) - def _asyncgen_fixture_wrapper(request: SubRequest, **kwargs: Any): + def _asyncgen_fixture_wrapper(request: FixtureRequest, **kwargs: Any): func = _perhaps_rebind_fixture_func( fixture, request.instance, fixturedef.unittest ) @@ -355,7 +354,7 @@ def _wrap_async_fixture(fixturedef: FixtureDef, event_loop_fixture_id: str) -> N fixture = fixturedef.func @functools.wraps(fixture) - def _async_fixture_wrapper(request: SubRequest, **kwargs: Any): + def _async_fixture_wrapper(request: FixtureRequest, **kwargs: Any): func = _perhaps_rebind_fixture_func( fixture, request.instance, fixturedef.unittest ) From 75db3c0b2db1a8c28c9b69a1fa67520696d16c1c Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 9 Mar 2024 22:08:19 +0200 Subject: [PATCH 2/4] Remove unused function `_removesuffix` --- pytest_asyncio/plugin.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/pytest_asyncio/plugin.py b/pytest_asyncio/plugin.py index 5bfb234e..4008d375 100644 --- a/pytest_asyncio/plugin.py +++ b/pytest_asyncio/plugin.py @@ -6,7 +6,6 @@ import functools import inspect import socket -import sys import warnings from asyncio import AbstractEventLoopPolicy from textwrap import dedent @@ -656,12 +655,6 @@ def _patched_collect(): collector.obj.__pytest_asyncio_scoped_event_loop = scoped_event_loop -def _removesuffix(s: str, suffix: str) -> str: - if sys.version_info < (3, 9): - return s[: -len(suffix)] - return s.removesuffix(suffix) - - @contextlib.contextmanager def _temporary_event_loop_policy(policy: AbstractEventLoopPolicy) -> Iterator[None]: old_loop_policy = asyncio.get_event_loop_policy() From ee8bd5fe6bc6998bbc47877b2759ff88addef81f Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 9 Mar 2024 21:51:53 +0200 Subject: [PATCH 3/4] Fix compatibility with pytest 8.2 FixtureDef.unittest removal Since pytest 8.2 unittest and regular behave the same, so unittest special handling is no longer needed. --- pytest_asyncio/plugin.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/pytest_asyncio/plugin.py b/pytest_asyncio/plugin.py index 4008d375..b2c5c59e 100644 --- a/pytest_asyncio/plugin.py +++ b/pytest_asyncio/plugin.py @@ -315,9 +315,8 @@ def _wrap_asyncgen_fixture(fixturedef: FixtureDef, event_loop_fixture_id: str) - @functools.wraps(fixture) def _asyncgen_fixture_wrapper(request: FixtureRequest, **kwargs: Any): - func = _perhaps_rebind_fixture_func( - fixture, request.instance, fixturedef.unittest - ) + unittest = False if pytest.version_tuple >= (8, 2) else fixturedef.unittest + func = _perhaps_rebind_fixture_func(fixture, request.instance, unittest) event_loop = kwargs.pop(event_loop_fixture_id) gen_obj = func( **_add_kwargs(func, kwargs, event_loop_fixture_id, event_loop, request) @@ -354,9 +353,8 @@ def _wrap_async_fixture(fixturedef: FixtureDef, event_loop_fixture_id: str) -> N @functools.wraps(fixture) def _async_fixture_wrapper(request: FixtureRequest, **kwargs: Any): - func = _perhaps_rebind_fixture_func( - fixture, request.instance, fixturedef.unittest - ) + unittest = False if pytest.version_tuple >= (8, 2) else fixturedef.unittest + func = _perhaps_rebind_fixture_func(fixture, request.instance, unittest) event_loop = kwargs.pop(event_loop_fixture_id) async def setup(): From 67226d5c4f7f775284742f2802c79a9b74ea3503 Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Tue, 19 Mar 2024 07:47:15 +0100 Subject: [PATCH 4/4] [docs] Mentioned pytest 8.2 compatibility fix in changelog. Signed-off-by: Michael Seifert --- docs/source/reference/changelog.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/source/reference/changelog.rst b/docs/source/reference/changelog.rst index 31f2d71e..198baf68 100644 --- a/docs/source/reference/changelog.rst +++ b/docs/source/reference/changelog.rst @@ -2,6 +2,15 @@ Changelog ========= +0.23.6 (2024-03-19) +=================== +- Fix compatibility with pytest 8.2 `#800 `_ + +Known issues +------------ +As of v0.23, pytest-asyncio attaches an asyncio event loop to each item of the test suite (i.e. session, packages, modules, classes, functions) and allows tests to be run in those loops when marked accordingly. Pytest-asyncio currently assumes that async fixture scope is correlated with the new event loop scope. This prevents fixtures from being evaluated independently from the event loop scope and breaks some existing test suites (see `#706`_). For example, a test suite may require all fixtures and tests to run in the same event loop, but have async fixtures that are set up and torn down for each module. If you're affected by this issue, please continue using the v0.21 release, until it is resolved. + + 0.23.5 (2024-02-09) =================== - Declare compatibility with pytest 8 `#737 `_