Skip to content
Closed
Show file tree
Hide file tree
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
1 change: 1 addition & 0 deletions changelog.d/1344.fixed.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Only warn about an unset ``asyncio_default_fixture_loop_scope`` configuration option when an async fixture is actually used.
22 changes: 15 additions & 7 deletions pytest_asyncio/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
PytestCollectionWarning,
PytestDeprecationWarning,
PytestPluginManager,
StashKey,
)

if sys.version_info >= (3, 11):
Expand Down Expand Up @@ -293,11 +294,19 @@ def _validate_scope(scope: str | None, option_name: str) -> None:
)


_DEFAULT_FIXTURE_LOOP_SCOPE_WARNING_EMITTED: StashKey[bool] = StashKey()


def _warn_default_fixture_loop_scope_unset(config: Config) -> None:
if config.stash.get(_DEFAULT_FIXTURE_LOOP_SCOPE_WARNING_EMITTED, False):
return
config.stash[_DEFAULT_FIXTURE_LOOP_SCOPE_WARNING_EMITTED] = True
warnings.warn(PytestDeprecationWarning(_DEFAULT_FIXTURE_LOOP_SCOPE_UNSET))


def pytest_configure(config: Config) -> None:
default_fixture_loop_scope = config.getini("asyncio_default_fixture_loop_scope")
_validate_scope(default_fixture_loop_scope, "asyncio_default_fixture_loop_scope")
if not default_fixture_loop_scope:
warnings.warn(PytestDeprecationWarning(_DEFAULT_FIXTURE_LOOP_SCOPE_UNSET))

default_test_loop_scope = config.getini("asyncio_default_test_loop_scope")
_validate_scope(default_test_loop_scope, "asyncio_default_test_loop_scope")
Expand Down Expand Up @@ -926,11 +935,10 @@ def pytest_fixture_setup(fixturedef: FixtureDef, request) -> object | None:
if not _is_coroutine_or_asyncgen(fixturedef.func):
return (yield)
default_loop_scope = request.config.getini("asyncio_default_fixture_loop_scope")
loop_scope = (
getattr(fixturedef.func, "_loop_scope", None)
or default_loop_scope
or fixturedef.scope
)
fixture_loop_scope = getattr(fixturedef.func, "_loop_scope", None)
loop_scope = fixture_loop_scope or default_loop_scope or fixturedef.scope
if not default_loop_scope and not fixture_loop_scope:
_warn_default_fixture_loop_scope_unset(request.config)
runner_fixture_id = f"_{loop_scope}_scoped_runner"
runner = request.getfixturevalue(runner_fixture_id)
# Prevent the runner closing before the fixture's async teardown.
Expand Down
45 changes: 45 additions & 0 deletions tests/test_fixture_loop_scopes.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,3 +126,48 @@ def test_invalid_default_fixture_loop_scope_raises_error(pytester: Pytester):
"function, class, module, package, session."
]
)


def test_no_warning_for_unset_default_fixture_loop_scope_without_async_fixtures(
pytester: Pytester,
):
"""Regression test for #1344."""
pytester.makeini(dedent("""\
[pytest]
asyncio_mode = strict
"""))
pytester.makepyfile(dedent("""\
def test_no_async():
pass
"""))
result = pytester.runpytest_subprocess("-Werror")
result.assert_outcomes(passed=1)


def test_warning_for_unset_default_fixture_loop_scope_with_async_fixture(
pytester: Pytester,
):
pytester.makeini(dedent("""\
[pytest]
asyncio_mode = strict
"""))
pytester.makepyfile(dedent("""\
import pytest
import pytest_asyncio

@pytest_asyncio.fixture
async def async_fixture():
return 42

@pytest.mark.asyncio
async def test_async(async_fixture):
assert async_fixture == 42
"""))
result = pytester.runpytest_subprocess("-Wdefault")
result.assert_outcomes(passed=1, warnings=1)
result.stdout.fnmatch_lines(
[
"*PytestDeprecationWarning: The configuration option "
'"asyncio_default_fixture_loop_scope" is unset.*'
]
)
Loading