Skip to content
Open
Show file tree
Hide file tree
Changes from 3 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
2 changes: 1 addition & 1 deletion changelog.d/1298.changed.rst
Comment thread
SahilArchitect marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Improved the readability of the warning message that is displayed when ``asyncio_default_fixture_loop_scope`` is unset
The default value of ``asyncio_default_fixture_loop_scope`` is now ``function``. The deprecated unset behavior and warning have been removed.
1 change: 1 addition & 0 deletions changelog.d/924.changed.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The default value of ``asyncio_default_fixture_loop_scope`` is now ``function``. The deprecated unset behavior and warning have been removed.
2 changes: 1 addition & 1 deletion docs/how-to-guides/migrate_from_0_21.rst
Comment thread
SahilArchitect marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ Go through all re-implemented *event_loop* fixtures in your test suite one by on
1. For all tests and fixtures affected by the re-implemented *event_loop* fixture, configure the *loop_scope* for async tests and fixtures to match the *event_loop* fixture scope. This can be done for each test and fixture individually using either the ``pytest.mark.asyncio(loop_scope="…")`` marker for async tests or ``@pytest_asyncio.fixture(loop_scope="…")`` for async fixtures. Alternatively, you can set the default loop scope for fixtures using the :ref:`asyncio_default_fixture_loop_scope <configuration/asyncio_default_fixture_loop_scope>` configuration option. Snippets to mark all tests with the same *asyncio* marker, thus sharing the same loop scope, are present in the how-to section of the documentation. Depending on the homogeneity of your test suite, you may want a mixture of explicit decorators and default settings.
2. Remove the re-implemented *event_loop* fixture.

If you haven't set the *asyncio_default_fixture_loop_scope* configuration option, yet, set it to *function* to silence the deprecation warning.
The *asyncio_default_fixture_loop_scope* configuration option now defaults to *function* when unset.
2 changes: 1 addition & 1 deletion docs/how-to-guides/migrate_from_0_23.rst
Comment thread
SahilArchitect marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ How to migrate from pytest-asyncio v0.23
The following steps assume that your test suite has no re-implementations of the *event_loop* fixture, nor explicit fixtures requests for it. If this isn't the case, please follow the :ref:`migration guide for pytest-asyncio v0.21. <how_to_guides/migrate_from_0_21>`

1. Explicitly set the *loop_scope* of async fixtures by replacing occurrences of ``@pytest.fixture(scope="…")`` and ``@pytest_asyncio.fixture(scope="…")`` with ``@pytest_asyncio.fixture(loop_scope="…", scope="…")`` such that *loop_scope* and *scope* are the same. If you use auto mode, resolve all import errors from missing imports of *pytest_asyncio*. If your async fixtures all use the same *loop_scope*, you may choose to set the *asyncio_default_fixture_loop_scope* configuration option to that loop scope, instead.
2. If you haven't set *asyncio_default_fixture_loop_scope*, set it to *function* to address the deprecation warning about the unset configuration option.
2. The *asyncio_default_fixture_loop_scope* configuration option now defaults to *function* when unset.
3. Change all occurrences of ``pytest.mark.asyncio(scope="…")`` to ``pytest.mark.asyncio(loop_scope="…")`` to address the deprecation warning about the *scope* argument to the *asyncio* marker.
20 changes: 2 additions & 18 deletions pytest_asyncio/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ def pytest_addoption(parser: Parser, pluginmanager: PytestPluginManager) -> None
"asyncio_default_fixture_loop_scope",
type="string",
help="default scope of the asyncio event loop used to execute async fixtures",
default=None,
default="function",
)
parser.addini(
"asyncio_default_test_loop_scope",
Expand Down Expand Up @@ -271,16 +271,6 @@ def _collect_hook_loop_factories(
return factories


_DEFAULT_FIXTURE_LOOP_SCOPE_UNSET = """\
The configuration option "asyncio_default_fixture_loop_scope" is unset.
The event loop scope for asynchronous fixtures will default to the "fixture" caching \
scope. Future versions of pytest-asyncio will default the loop scope for asynchronous \
fixtures to "function" scope. Set the default fixture loop scope explicitly in order \
to avoid unexpected behavior in the future. Valid fixture loop scopes are: \
"function", "class", "module", "package", "session"
"""


def _validate_scope(scope: str | None, option_name: str) -> None:
if scope is None:
return
Expand All @@ -295,8 +285,6 @@ def _validate_scope(scope: str | None, option_name: str) -> None:
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 @@ -925,11 +913,7 @@ 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
)
loop_scope = getattr(fixturedef.func, "_loop_scope", None) or default_loop_scope
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
23 changes: 23 additions & 0 deletions tests/test_fixture_loop_scopes.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,29 @@ async def test_runs_in_same_loop_as_fixture(fixture):
result.assert_outcomes(passed=1)


def test_default_fixture_loop_scope_is_function_when_unset(pytester: Pytester):
Comment thread
SahilArchitect marked this conversation as resolved.
pytester.makepyfile(dedent("""
import pytest
import pytest_asyncio

@pytest_asyncio.fixture
async def value():
return 1

@pytest.mark.asyncio
async def test_value(value):
assert value == 1
"""))

result = pytester.runpytest_subprocess("--asyncio-mode=strict", "-W", "error")
result.assert_outcomes(passed=1)
result.stdout.fnmatch_lines(
[
"*asyncio_default_fixture_loop_scope=function*",
]
)


@pytest.mark.parametrize("default_loop_scope", ("function", "module", "session"))
def test_default_loop_scope_config_option_changes_fixture_loop_scope(
pytester: Pytester,
Expand Down
Loading