From a4d64c8f6b56ac82610dc2f10447e7498257aed6 Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Thu, 25 Jul 2024 09:23:48 +0200 Subject: [PATCH] docs: Updated documentation on decorators to address the addition of the loop_scope keyword argument. Signed-off-by: Michael Seifert --- docs/source/concepts.rst | 2 ++ .../decorators/fixture_strict_mode_example.py | 14 ----------- docs/source/reference/decorators/index.rst | 23 +++++++++++-------- .../pytest_asyncio_fixture_example.py | 17 ++++++++++++++ 4 files changed, 33 insertions(+), 23 deletions(-) delete mode 100644 docs/source/reference/decorators/fixture_strict_mode_example.py create mode 100644 docs/source/reference/decorators/pytest_asyncio_fixture_example.py diff --git a/docs/source/concepts.rst b/docs/source/concepts.rst index 298d08f2..be8b775b 100644 --- a/docs/source/concepts.rst +++ b/docs/source/concepts.rst @@ -2,6 +2,8 @@ Concepts ======== +.. _concepts/event_loops: + asyncio event loops =================== In order to understand how pytest-asyncio works, it helps to understand how pytest collectors work. diff --git a/docs/source/reference/decorators/fixture_strict_mode_example.py b/docs/source/reference/decorators/fixture_strict_mode_example.py deleted file mode 100644 index 6442c103..00000000 --- a/docs/source/reference/decorators/fixture_strict_mode_example.py +++ /dev/null @@ -1,14 +0,0 @@ -import asyncio - -import pytest_asyncio - - -@pytest_asyncio.fixture -async def async_gen_fixture(): - await asyncio.sleep(0.1) - yield "a value" - - -@pytest_asyncio.fixture(scope="module") -async def async_fixture(): - return await asyncio.sleep(0.1) diff --git a/docs/source/reference/decorators/index.rst b/docs/source/reference/decorators/index.rst index c049c5dd..0fcb7087 100644 --- a/docs/source/reference/decorators/index.rst +++ b/docs/source/reference/decorators/index.rst @@ -3,15 +3,20 @@ ========== Decorators ========== -Asynchronous fixtures are defined just like ordinary pytest fixtures, except they should be decorated with ``@pytest_asyncio.fixture``. +The ``@pytest_asyncio.fixture`` decorator allows coroutines and async generator functions to be used as pytest fixtures. -.. include:: fixture_strict_mode_example.py - :code: python +The decorator takes all arguments supported by `@pytest.fixture`. +Additionally, ``@pytest_asyncio.fixture`` supports the *loop_scope* keyword argument, which selects the event loop in which the fixture is run (see :ref:`concepts/event_loops`). +The default event loop scope is *function* scope. +Possible loop scopes are *session,* *package,* *module,* *class,* and *function*. + +The *loop_scope* of a fixture can be chosen independently from its caching *scope*. +However, the event loop scope must be larger or the same as the fixture's caching scope. +In other words, it's possible to reevaluate an async fixture multiple times within the same event loop, but it's not possible to switch out the running event loop in an async fixture. -All scopes are supported, but if you use a non-function scope you will need -to redefine the ``event_loop`` fixture to have the same or broader scope. -Async fixtures need the event loop, and so must have the same or narrower scope -than the ``event_loop`` fixture. +Examples: + +.. include:: pytest_asyncio_fixture_example.py + :code: python -*auto* mode automatically converts async fixtures declared with the -standard ``@pytest.fixture`` decorator to *asyncio-driven* versions. +*auto* mode automatically converts coroutines and async generator functions declared with the standard ``@pytest.fixture`` decorator to pytest-asyncio fixtures. diff --git a/docs/source/reference/decorators/pytest_asyncio_fixture_example.py b/docs/source/reference/decorators/pytest_asyncio_fixture_example.py new file mode 100644 index 00000000..3123f11d --- /dev/null +++ b/docs/source/reference/decorators/pytest_asyncio_fixture_example.py @@ -0,0 +1,17 @@ +import pytest_asyncio + + +@pytest_asyncio.fixture +async def fixture_runs_in_fresh_loop_for_every_function(): ... + + +@pytest_asyncio.fixture(loop_scope="session", scope="module") +async def fixture_runs_in_session_loop_once_per_module(): ... + + +@pytest_asyncio.fixture(loop_scope="module", scope="module") +async def fixture_runs_in_module_loop_once_per_module(): ... + + +@pytest_asyncio.fixture(loop_scope="module") +async def fixture_runs_in_module_loop_once_per_function(): ...