Skip to content

Commit

Permalink
[fix] Fixes an issue that causes DeprecationWarnings for event loop o…
Browse files Browse the repository at this point in the history
…verrides to be emitted, even though the fixture was not overridden.

Signed-off-by: Michael Seifert <m.seifert@digitalernachschub.de>
  • Loading branch information
seifertm committed Oct 27, 2023
1 parent b7c66db commit 9f75b3c
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 18 deletions.
33 changes: 16 additions & 17 deletions pytest_asyncio/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -646,17 +646,6 @@ def pytest_fixture_setup(
) -> Optional[object]:
"""Adjust the event loop policy when an event loop is produced."""
if fixturedef.argname == "event_loop":
# FixtureDef.baseid is an empty string when the Fixture was found in a plugin.
# This is also true, when the fixture was defined in a conftest.py
# at the rootdir.
fixture_filename = inspect.getsourcefile(fixturedef.func)
if not getattr(fixturedef.func, "__original_func", False):
_, fixture_line_number = inspect.getsourcelines(fixturedef.func)
warnings.warn(
_REDEFINED_EVENT_LOOP_FIXTURE_WARNING
% (fixture_filename, fixture_line_number),
DeprecationWarning,
)
# The use of a fixture finalizer is preferred over the
# pytest_fixture_post_finalizer hook. The fixture finalizer is invoked once
# for each fixture, whereas the hook may be invoked multiple times for
Expand All @@ -669,6 +658,16 @@ def pytest_fixture_setup(
)
outcome = yield
loop = outcome.get_result()
# Weird behavior was observed when checking for an attribute of FixtureDef.func
# Instead, we now check for a special attribute of the returned event loop
fixture_filename = inspect.getsourcefile(fixturedef.func)
if not getattr(loop, "__original_fixture_loop", False):
_, fixture_line_number = inspect.getsourcelines(fixturedef.func)
warnings.warn(
_REDEFINED_EVENT_LOOP_FIXTURE_WARNING
% (fixture_filename, fixture_line_number),
DeprecationWarning,
)
policy = asyncio.get_event_loop_policy()
try:
with warnings.catch_warnings():
Expand Down Expand Up @@ -836,13 +835,13 @@ def pytest_runtest_setup(item: pytest.Item) -> None:
@pytest.fixture
def event_loop(request: FixtureRequest) -> Iterator[asyncio.AbstractEventLoop]:
"""Create an instance of the default event loop for each test case."""
# Add a magic value to the fixture function, so that we can check for overrides
# of this fixture in pytest_fixture_setup
# The magic value must be part of the function definition, because pytest may have
# multiple instances of the fixture function
event_loop.__original_func = True

loop = asyncio.get_event_loop_policy().new_event_loop()
# Add a magic value to the event loop, so pytest-asyncio can determine if the
# event_loop fixture was overridden. Other implementations of event_loop don't
# set this value.
# The magic value must be set as part of the function definition, because pytest
# seems to have multiple instances of the same FixtureDef or fixture function
loop.__original_fixture_loop = True # type: ignore[attr-defined]
yield loop
loop.close()

Expand Down
2 changes: 1 addition & 1 deletion tests/test_event_loop_fixture_finalizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,5 +133,5 @@ async def test_ends_with_unclosed_loop():
)
)
result = pytester.runpytest("--asyncio-mode=strict", "-W", "default")
result.assert_outcomes(passed=1, warnings=2)
result.assert_outcomes(passed=1, warnings=1)
result.stdout.fnmatch_lines("*unclosed event loop*")

0 comments on commit 9f75b3c

Please sign in to comment.