Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 28 additions & 30 deletions pytest_asyncio/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -442,8 +442,25 @@ def _can_substitute(item: Function) -> bool:
"""Returns whether the specified function can be replaced by this class"""
raise NotImplementedError()

def setup(self) -> None:
runner_fixture_id = f"_{self._loop_scope}_scoped_runner"
if runner_fixture_id not in self.fixturenames:
self.fixturenames.append(runner_fixture_id)
return super().setup()

def runtest(self) -> None:
runner_fixture_id = f"_{self._loop_scope}_scoped_runner"
runner = self._request.getfixturevalue(runner_fixture_id)
context = contextvars.copy_context()
synchronized_obj = _synchronize_coroutine(
getattr(*self._synchronization_target_attr), runner, context
)
with MonkeyPatch.context() as c:
c.setattr(*self._synchronization_target_attr, synchronized_obj)
super().runtest()

@functools.cached_property
def loop_scope(self) -> _ScopeName:
def _loop_scope(self) -> _ScopeName:
"""
Return the scope of the asyncio event loop this item is run in.

Expand All @@ -457,17 +474,6 @@ def loop_scope(self) -> _ScopeName:
default_loop_scope = _get_default_test_loop_scope(self.config)
return _get_marked_loop_scope(marker, default_loop_scope)

def runtest(self) -> None:
runner_fixture_id = f"_{self.loop_scope}_scoped_runner"
runner = self._request.getfixturevalue(runner_fixture_id)
context = contextvars.copy_context()
synchronized_obj = _synchronize_coroutine(
getattr(*self._synchronization_target_attr), runner, context
)
with MonkeyPatch.context() as c:
c.setattr(*self._synchronization_target_attr, synchronized_obj)
super().runtest()

@property
def _synchronization_target_attr(self) -> tuple[object, str]:
"""
Expand Down Expand Up @@ -531,6 +537,16 @@ class AsyncHypothesisTest(PytestAsyncioFunction):
@hypothesis.given.
"""

def setup(self) -> None:
if not getattr(self.obj, "hypothesis", False) and getattr(
self.obj, "is_hypothesis_test", False
):
pytest.fail(
f"test function `{self!r}` is using Hypothesis, but pytest-asyncio "
"only works with Hypothesis 3.64.0 or later."
)
return super().setup()

@staticmethod
def _can_substitute(item: Function) -> bool:
func = item.obj
Expand Down Expand Up @@ -693,24 +709,6 @@ def inner(*args, **kwargs):
return inner


def pytest_runtest_setup(item: pytest.Item) -> None:
marker = item.get_closest_marker("asyncio")
if marker is None or not is_async_test(item):
return
runner_fixture_id = f"_{item.loop_scope}_scoped_runner"
fixturenames = item.fixturenames # type: ignore[attr-defined]
if runner_fixture_id not in fixturenames:
fixturenames.append(runner_fixture_id)
obj = getattr(item, "obj", None)
if not getattr(obj, "hypothesis", False) and getattr(
obj, "is_hypothesis_test", False
):
pytest.fail(
f"test function `{item!r}` is using Hypothesis, but pytest-asyncio "
"only works with Hypothesis 3.64.0 or later."
)


@pytest.hookimpl(wrapper=True)
def pytest_fixture_setup(fixturedef: FixtureDef, request) -> object | None:
asyncio_mode = _get_asyncio_mode(request.config)
Expand Down
Loading