From 66bc053310ea36b664b2b0bf1ec016a5bc075761 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Jul 2024 18:27:39 +0000 Subject: [PATCH 001/226] Build(deps): Bump sphinx from 7.3.7 to 7.4.4 in /dependencies/docs Bumps [sphinx](https://github.com/sphinx-doc/sphinx) from 7.3.7 to 7.4.4. - [Release notes](https://github.com/sphinx-doc/sphinx/releases) - [Changelog](https://github.com/sphinx-doc/sphinx/blob/master/CHANGES.rst) - [Commits](https://github.com/sphinx-doc/sphinx/compare/v7.3.7...v7.4.4) --- updated-dependencies: - dependency-name: sphinx dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- dependencies/docs/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/docs/constraints.txt b/dependencies/docs/constraints.txt index 4c187a1e..ea1d462d 100644 --- a/dependencies/docs/constraints.txt +++ b/dependencies/docs/constraints.txt @@ -11,7 +11,7 @@ packaging==24.1 Pygments==2.18.0 requests==2.32.3 snowballstemmer==2.2.0 -Sphinx==7.3.7 +Sphinx==7.4.4 sphinx-rtd-theme==2.0.0 sphinxcontrib-applehelp==1.0.8 sphinxcontrib-devhelp==1.0.6 From 799c9053901135c40a9fc0802fcbee1d20f4e42a Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Wed, 17 Jul 2024 19:42:09 +0200 Subject: [PATCH 002/226] build: Bump dependency on docutils to v0.20.1. --- dependencies/docs/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/docs/constraints.txt b/dependencies/docs/constraints.txt index ea1d462d..1b2cda96 100644 --- a/dependencies/docs/constraints.txt +++ b/dependencies/docs/constraints.txt @@ -2,7 +2,7 @@ alabaster==0.7.16 Babel==2.15.0 certifi==2024.7.4 charset-normalizer==3.3.2 -docutils==0.18.1 +docutils==0.20.1 idna==3.7 imagesize==1.4.1 Jinja2==3.1.4 From 97bd934698798134bf23ce4ed22ed61c8b8f70b0 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 15 Jul 2024 22:26:09 +0000 Subject: [PATCH 003/226] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/pre-commit-hooks: v4.3.0 → v4.6.0](https://github.com/pre-commit/pre-commit-hooks/compare/v4.3.0...v4.6.0) - [github.com/asottile/yesqa: v1.4.0 → v1.5.0](https://github.com/asottile/yesqa/compare/v1.4.0...v1.5.0) - [github.com/Zac-HD/shed: 2024.1.1 → 2024.3.1](https://github.com/Zac-HD/shed/compare/2024.1.1...2024.3.1) - [github.com/jumanjihouse/pre-commit-hook-yamlfmt: 0.2.2 → 0.2.3](https://github.com/jumanjihouse/pre-commit-hook-yamlfmt/compare/0.2.2...0.2.3) - [github.com/pre-commit/pre-commit-hooks: v4.3.0 → v4.6.0](https://github.com/pre-commit/pre-commit-hooks/compare/v4.3.0...v4.6.0) - [github.com/pre-commit/mirrors-mypy: v1.8.0 → v1.10.1](https://github.com/pre-commit/mirrors-mypy/compare/v1.8.0...v1.10.1) - [github.com/pycqa/flake8: 6.1.0 → 7.1.0](https://github.com/pycqa/flake8/compare/6.1.0...7.1.0) - [github.com/pre-commit/pygrep-hooks: v1.9.0 → v1.10.0](https://github.com/pre-commit/pygrep-hooks/compare/v1.9.0...v1.10.0) - [github.com/sirosen/check-jsonschema: 0.19.2 → 0.29.0](https://github.com/sirosen/check-jsonschema/compare/0.19.2...0.29.0) [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci fix: Address type error about missing return statement. --- .pre-commit-config.yaml | 18 +++++++++--------- docs/source/reference/fixtures/index.rst | 3 +-- pytest_asyncio/plugin.py | 5 +++-- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f83159c1..73f59d79 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,16 +1,16 @@ --- repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.3.0 + rev: v4.6.0 hooks: - id: check-merge-conflict exclude: rst$ - repo: https://github.com/asottile/yesqa - rev: v1.4.0 + rev: v1.5.0 hooks: - id: yesqa - repo: https://github.com/Zac-HD/shed - rev: 2024.1.1 + rev: 2024.3.1 hooks: - id: shed args: @@ -20,12 +20,12 @@ repos: - markdown - rst - repo: https://github.com/jumanjihouse/pre-commit-hook-yamlfmt - rev: 0.2.2 + rev: 0.2.3 hooks: - id: yamlfmt args: [--mapping, '2', --sequence, '2', --offset, '0'] - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.3.0 + rev: v4.6.0 hooks: - id: trailing-whitespace - id: end-of-file-fixer @@ -37,23 +37,23 @@ repos: - id: check-yaml - id: debug-statements - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.8.0 + rev: v1.10.1 hooks: - id: mypy exclude: ^(docs|tests)/.* additional_dependencies: - pytest - repo: https://github.com/pycqa/flake8 - rev: 6.1.0 + rev: 7.1.0 hooks: - id: flake8 language_version: python3 - repo: https://github.com/pre-commit/pygrep-hooks - rev: v1.9.0 + rev: v1.10.0 hooks: - id: python-use-type-annotations - repo: https://github.com/sirosen/check-jsonschema - rev: 0.19.2 + rev: 0.29.0 hooks: - id: check-github-actions ci: diff --git a/docs/source/reference/fixtures/index.rst b/docs/source/reference/fixtures/index.rst index 7b8dc818..37eec503 100644 --- a/docs/source/reference/fixtures/index.rst +++ b/docs/source/reference/fixtures/index.rst @@ -51,8 +51,7 @@ when several unused TCP ports are required in a test. .. code-block:: python def a_test(unused_tcp_port_factory): - port1, port2 = unused_tcp_port_factory(), unused_tcp_port_factory() - ... + _port1, _port2 = unused_tcp_port_factory(), unused_tcp_port_factory() unused_udp_port and unused_udp_port_factory =========================================== diff --git a/pytest_asyncio/plugin.py b/pytest_asyncio/plugin.py index d3d1fcf7..04a7faca 100644 --- a/pytest_asyncio/plugin.py +++ b/pytest_asyncio/plugin.py @@ -882,6 +882,7 @@ def pytest_pyfunc_call(pyfuncitem: Function) -> Optional[object]: ) ) yield + return None def wrap_in_sync( @@ -946,8 +947,8 @@ def pytest_runtest_setup(item: pytest.Item) -> None: obj, "is_hypothesis_test", False ): pytest.fail( - "test function `%r` is using Hypothesis, but pytest-asyncio " - "only works with Hypothesis 3.64.0 or later." % item + f"test function `{item!r}` is using Hypothesis, but pytest-asyncio " + "only works with Hypothesis 3.64.0 or later." ) From 5af32d6fcdc8bc2940f766b03ac17c5ee01a0fd5 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 22 Jul 2024 22:32:49 +0000 Subject: [PATCH 004/226] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/mirrors-mypy: v1.10.1 → v1.11.0](https://github.com/pre-commit/mirrors-mypy/compare/v1.10.1...v1.11.0) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 73f59d79..932e0d48 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -37,7 +37,7 @@ repos: - id: check-yaml - id: debug-statements - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.10.1 + rev: v1.11.0 hooks: - id: mypy exclude: ^(docs|tests)/.* From ebdf3d68d2a5c19f3586e6d1f1d82b142718ce8a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jul 2024 18:24:33 +0000 Subject: [PATCH 005/226] Build(deps): Bump hypothesis in /dependencies/default Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.108.2 to 6.108.4. - [Release notes](https://github.com/HypothesisWorks/hypothesis/releases) - [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.108.2...hypothesis-python-6.108.4) --- updated-dependencies: - dependency-name: hypothesis dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index 2ccf269e..5bbd1b5d 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -1,7 +1,7 @@ attrs==23.2.0 coverage==7.6.0 exceptiongroup==1.2.2 -hypothesis==6.108.2 +hypothesis==6.108.4 iniconfig==2.0.0 packaging==24.1 pluggy==1.5.0 From faa81e07a366271e150413a258c24027a7dbb883 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jul 2024 18:24:27 +0000 Subject: [PATCH 006/226] Build(deps): Bump pytest from 8.2.2 to 8.3.1 in /dependencies/default Bumps [pytest](https://github.com/pytest-dev/pytest) from 8.2.2 to 8.3.1. - [Release notes](https://github.com/pytest-dev/pytest/releases) - [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest/compare/8.2.2...8.3.1) --- updated-dependencies: - dependency-name: pytest dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index 5bbd1b5d..fb19721a 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -5,7 +5,7 @@ hypothesis==6.108.4 iniconfig==2.0.0 packaging==24.1 pluggy==1.5.0 -pytest==8.2.2 +pytest==8.3.1 sortedcontainers==2.4.0 tomli==2.0.1 typing_extensions==4.12.2 From fd67068249f3f01c8d52a153f872062cac9df74e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jul 2024 18:19:51 +0000 Subject: [PATCH 007/226] Build(deps): Bump sphinxcontrib-qthelp in /dependencies/docs Bumps [sphinxcontrib-qthelp](https://github.com/sphinx-doc/sphinxcontrib-qthelp) from 1.0.7 to 1.0.8. - [Release notes](https://github.com/sphinx-doc/sphinxcontrib-qthelp/releases) - [Changelog](https://github.com/sphinx-doc/sphinxcontrib-qthelp/blob/master/CHANGES) - [Commits](https://github.com/sphinx-doc/sphinxcontrib-qthelp/compare/1.0.7...1.0.8) --- updated-dependencies: - dependency-name: sphinxcontrib-qthelp dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dependencies/docs/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/docs/constraints.txt b/dependencies/docs/constraints.txt index 1b2cda96..d3e384a4 100644 --- a/dependencies/docs/constraints.txt +++ b/dependencies/docs/constraints.txt @@ -18,6 +18,6 @@ sphinxcontrib-devhelp==1.0.6 sphinxcontrib-htmlhelp==2.0.5 sphinxcontrib-jquery==4.1 sphinxcontrib-jsmath==1.0.1 -sphinxcontrib-qthelp==1.0.7 +sphinxcontrib-qthelp==1.0.8 sphinxcontrib-serializinghtml==1.1.10 urllib3==2.2.2 From bea2dca99abe076b6f5e08574722432461878833 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jul 2024 18:19:48 +0000 Subject: [PATCH 008/226] Build(deps): Bump sphinx from 7.4.4 to 7.4.7 in /dependencies/docs Bumps [sphinx](https://github.com/sphinx-doc/sphinx) from 7.4.4 to 7.4.7. - [Release notes](https://github.com/sphinx-doc/sphinx/releases) - [Changelog](https://github.com/sphinx-doc/sphinx/blob/master/CHANGES.rst) - [Commits](https://github.com/sphinx-doc/sphinx/compare/v7.4.4...v7.4.7) --- updated-dependencies: - dependency-name: sphinx dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dependencies/docs/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/docs/constraints.txt b/dependencies/docs/constraints.txt index d3e384a4..336ef01f 100644 --- a/dependencies/docs/constraints.txt +++ b/dependencies/docs/constraints.txt @@ -11,7 +11,7 @@ packaging==24.1 Pygments==2.18.0 requests==2.32.3 snowballstemmer==2.2.0 -Sphinx==7.4.4 +Sphinx==7.4.7 sphinx-rtd-theme==2.0.0 sphinxcontrib-applehelp==1.0.8 sphinxcontrib-devhelp==1.0.6 From a56bb3f066e51644a7c8c99a4333ca5ffb5f727d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jul 2024 18:19:44 +0000 Subject: [PATCH 009/226] Build(deps): Bump sphinxcontrib-htmlhelp in /dependencies/docs Bumps [sphinxcontrib-htmlhelp](https://github.com/sphinx-doc/sphinxcontrib-htmlhelp) from 2.0.5 to 2.0.6. - [Release notes](https://github.com/sphinx-doc/sphinxcontrib-htmlhelp/releases) - [Changelog](https://github.com/sphinx-doc/sphinxcontrib-htmlhelp/blob/master/CHANGES) - [Commits](https://github.com/sphinx-doc/sphinxcontrib-htmlhelp/compare/2.0.5...2.0.6) --- updated-dependencies: - dependency-name: sphinxcontrib-htmlhelp dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dependencies/docs/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/docs/constraints.txt b/dependencies/docs/constraints.txt index 336ef01f..9906c5fa 100644 --- a/dependencies/docs/constraints.txt +++ b/dependencies/docs/constraints.txt @@ -15,7 +15,7 @@ Sphinx==7.4.7 sphinx-rtd-theme==2.0.0 sphinxcontrib-applehelp==1.0.8 sphinxcontrib-devhelp==1.0.6 -sphinxcontrib-htmlhelp==2.0.5 +sphinxcontrib-htmlhelp==2.0.6 sphinxcontrib-jquery==4.1 sphinxcontrib-jsmath==1.0.1 sphinxcontrib-qthelp==1.0.8 From 72a7006cec6b51f1fbc628683e35cf2e950ccfad Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 29 Jul 2024 22:26:06 +0000 Subject: [PATCH 010/226] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/sirosen/check-jsonschema: 0.29.0 → 0.29.1](https://github.com/sirosen/check-jsonschema/compare/0.29.0...0.29.1) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 932e0d48..5c49fd36 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -53,7 +53,7 @@ repos: hooks: - id: python-use-type-annotations - repo: https://github.com/sirosen/check-jsonschema - rev: 0.29.0 + rev: 0.29.1 hooks: - id: check-github-actions ci: From e8dde1cd8b83f37efb99f6905f8fb21cd4675f98 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Jul 2024 18:40:35 +0000 Subject: [PATCH 011/226] Build(deps): Bump hypothesis in /dependencies/default Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.108.4 to 6.108.5. - [Release notes](https://github.com/HypothesisWorks/hypothesis/releases) - [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.108.4...hypothesis-python-6.108.5) --- updated-dependencies: - dependency-name: hypothesis dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index fb19721a..49b595f0 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -1,7 +1,7 @@ attrs==23.2.0 coverage==7.6.0 exceptiongroup==1.2.2 -hypothesis==6.108.4 +hypothesis==6.108.5 iniconfig==2.0.0 packaging==24.1 pluggy==1.5.0 From ed34816510d6f27a12d1f3305b781a37a9bba6e4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Jul 2024 18:40:40 +0000 Subject: [PATCH 012/226] Build(deps): Bump pytest from 8.3.1 to 8.3.2 in /dependencies/default Bumps [pytest](https://github.com/pytest-dev/pytest) from 8.3.1 to 8.3.2. - [Release notes](https://github.com/pytest-dev/pytest/releases) - [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest/compare/8.3.1...8.3.2) --- updated-dependencies: - dependency-name: pytest dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index 49b595f0..2ea3a028 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -5,7 +5,7 @@ hypothesis==6.108.5 iniconfig==2.0.0 packaging==24.1 pluggy==1.5.0 -pytest==8.3.1 +pytest==8.3.2 sortedcontainers==2.4.0 tomli==2.0.1 typing_extensions==4.12.2 From 406b7a95c53d34767408bcdb044df3f5fcb1de49 Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Fri, 5 Jul 2024 14:07:59 +0200 Subject: [PATCH 013/226] [feat] Added optional "loop_scope" argument to pytest_asyncio.fixture. Signed-off-by: Michael Seifert --- pytest_asyncio/plugin.py | 19 +++++++++++++------ tests/test_fixture_loop_scopes.py | 19 +++++++++++++++++++ 2 files changed, 32 insertions(+), 6 deletions(-) create mode 100644 tests/test_fixture_loop_scopes.py diff --git a/pytest_asyncio/plugin.py b/pytest_asyncio/plugin.py index 04a7faca..22247c96 100644 --- a/pytest_asyncio/plugin.py +++ b/pytest_asyncio/plugin.py @@ -110,6 +110,7 @@ def fixture( fixture_function: FixtureFunction, *, scope: "Union[_ScopeName, Callable[[str, Config], _ScopeName]]" = ..., + loop_scope: Union[_ScopeName, None] = ..., params: Optional[Iterable[object]] = ..., autouse: bool = ..., ids: Union[ @@ -126,6 +127,7 @@ def fixture( fixture_function: None = ..., *, scope: "Union[_ScopeName, Callable[[str, Config], _ScopeName]]" = ..., + loop_scope: Union[_ScopeName, None] = ..., params: Optional[Iterable[object]] = ..., autouse: bool = ..., ids: Union[ @@ -138,17 +140,19 @@ def fixture( def fixture( - fixture_function: Optional[FixtureFunction] = None, **kwargs: Any + fixture_function: Optional[FixtureFunction] = None, + loop_scope: Union[_ScopeName, None] = None, + **kwargs: Any, ) -> Union[FixtureFunction, FixtureFunctionMarker]: if fixture_function is not None: - _make_asyncio_fixture_function(fixture_function) + _make_asyncio_fixture_function(fixture_function, loop_scope) return pytest.fixture(fixture_function, **kwargs) else: @functools.wraps(fixture) def inner(fixture_function: FixtureFunction) -> FixtureFunction: - return fixture(fixture_function, **kwargs) + return fixture(fixture_function, loop_scope=loop_scope, **kwargs) return inner @@ -158,11 +162,14 @@ def _is_asyncio_fixture_function(obj: Any) -> bool: return getattr(obj, "_force_asyncio_fixture", False) -def _make_asyncio_fixture_function(obj: Any) -> None: +def _make_asyncio_fixture_function( + obj: Any, loop_scope: Union[_ScopeName, None] +) -> None: if hasattr(obj, "__func__"): # instance method, check the function object obj = obj.__func__ obj._force_asyncio_fixture = True + obj._loop_scope = loop_scope def _is_coroutine_or_asyncgen(obj: Any) -> bool: @@ -218,7 +225,7 @@ def _preprocess_async_fixtures( # Ignore async fixtures without explicit asyncio mark in strict mode # This applies to pytest_trio fixtures, for example continue - scope = fixturedef.scope + scope = getattr(func, "_loop_scope", None) or fixturedef.scope if scope == "function": event_loop_fixture_id: Optional[str] = "event_loop" else: @@ -228,7 +235,7 @@ def _preprocess_async_fixtures( _event_loop_fixture_id, # type: ignore[arg-type] None, ) - _make_asyncio_fixture_function(func) + _make_asyncio_fixture_function(func, scope) function_signature = inspect.signature(func) if "event_loop" in function_signature.parameters: warnings.warn( diff --git a/tests/test_fixture_loop_scopes.py b/tests/test_fixture_loop_scopes.py new file mode 100644 index 00000000..91c5a089 --- /dev/null +++ b/tests/test_fixture_loop_scopes.py @@ -0,0 +1,19 @@ +import asyncio + +import pytest + +import pytest_asyncio + +loop: asyncio.AbstractEventLoop + + +@pytest_asyncio.fixture(loop_scope="session") +async def fixture(): + global loop + loop = asyncio.get_running_loop() + + +@pytest.mark.asyncio(scope="session") +async def test_fixture_loop_scopes(fixture): + global loop + assert loop == asyncio.get_running_loop() From c7c85b505a7cc70b36540c9a01dbe565a456b142 Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Fri, 5 Jul 2024 14:35:49 +0200 Subject: [PATCH 014/226] [test] Test the "loop_scope=session" argument to pytest_asyncio.fixture with additional pytest fixture scopes. Signed-off-by: Michael Seifert --- tests/test_fixture_loop_scopes.py | 41 ++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/tests/test_fixture_loop_scopes.py b/tests/test_fixture_loop_scopes.py index 91c5a089..1f4d0a35 100644 --- a/tests/test_fixture_loop_scopes.py +++ b/tests/test_fixture_loop_scopes.py @@ -1,19 +1,36 @@ -import asyncio +from textwrap import dedent import pytest +from pytest import Pytester -import pytest_asyncio -loop: asyncio.AbstractEventLoop +@pytest.mark.parametrize( + "fixture_scope", ("session", "package", "module", "class", "function") +) +def test_loop_scope_session_is_independent_of_fixture_scope( + pytester: Pytester, + fixture_scope: str, +): + pytester.makepyfile( + dedent( + f"""\ + import asyncio + import pytest + import pytest_asyncio + loop: asyncio.AbstractEventLoop = None -@pytest_asyncio.fixture(loop_scope="session") -async def fixture(): - global loop - loop = asyncio.get_running_loop() + @pytest_asyncio.fixture(scope="{fixture_scope}", loop_scope="session") + async def fixture(): + global loop + loop = asyncio.get_running_loop() - -@pytest.mark.asyncio(scope="session") -async def test_fixture_loop_scopes(fixture): - global loop - assert loop == asyncio.get_running_loop() + @pytest.mark.asyncio(scope="session") + async def test_runs_in_same_loop_as_fixture(fixture): + global loop + assert loop == asyncio.get_running_loop() + """ + ) + ) + result = pytester.runpytest_subprocess("--asyncio-mode=strict") + result.assert_outcomes(passed=1) From c938619eeadbd160750265a6fb8722afa664ae69 Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Tue, 9 Jul 2024 08:15:16 +0200 Subject: [PATCH 015/226] [refactor] Improve exception handling in pytest_pycollect_makeitem_convert_async_functions_to_subclass. Signed-off-by: Michael Seifert --- pytest_asyncio/plugin.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/pytest_asyncio/plugin.py b/pytest_asyncio/plugin.py index 22247c96..36c2dbf5 100644 --- a/pytest_asyncio/plugin.py +++ b/pytest_asyncio/plugin.py @@ -542,9 +542,16 @@ def pytest_pycollect_makeitem_convert_async_functions_to_subclass( to AsyncFunction items. """ hook_result = yield - node_or_list_of_nodes: Union[ - pytest.Item, pytest.Collector, List[Union[pytest.Item, pytest.Collector]], None - ] = hook_result.get_result() + try: + node_or_list_of_nodes: Union[ + pytest.Item, + pytest.Collector, + List[Union[pytest.Item, pytest.Collector]], + None, + ] = hook_result.get_result() + except BaseException as e: + hook_result.force_exception(e) + return if not node_or_list_of_nodes: return if isinstance(node_or_list_of_nodes, Sequence): From c74d1c3fba1afac0b8316763257c915bfba5f5e3 Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Tue, 9 Jul 2024 13:17:53 +0200 Subject: [PATCH 016/226] [feat] Added the asyncio_default_fixture_loop_scope configuration option. Signed-off-by: Michael Seifert --- docs/source/reference/configuration.rst | 6 ++ pytest_asyncio/plugin.py | 30 ++++++- tests/test_fixture_loop_scopes.py | 100 ++++++++++++++++++++++++ 3 files changed, 133 insertions(+), 3 deletions(-) diff --git a/docs/source/reference/configuration.rst b/docs/source/reference/configuration.rst index 5d840c47..7b0d1f95 100644 --- a/docs/source/reference/configuration.rst +++ b/docs/source/reference/configuration.rst @@ -2,6 +2,12 @@ Configuration ============= +asyncio_default_fixture_loop_scope +================================== +Determines the default event loop scope of asynchronous fixtures. When this configuration option is unset, it defaults to the fixture scope. In future versions of pytest-asyncio, the value will default to ``function`` when unset. Possible values are: ``function``, ``class``, ``module``, ``package``, ``session`` + +asyncio_mode +============ The pytest-asyncio mode can be set by the ``asyncio_mode`` configuration option in the `configuration file `_: diff --git a/pytest_asyncio/plugin.py b/pytest_asyncio/plugin.py index 36c2dbf5..d7618c1b 100644 --- a/pytest_asyncio/plugin.py +++ b/pytest_asyncio/plugin.py @@ -103,6 +103,12 @@ def pytest_addoption(parser: Parser, pluginmanager: PytestPluginManager) -> None help="default value for --asyncio-mode", default="strict", ) + parser.addini( + "asyncio_default_fixture_loop_scope", + type="string", + help="default scope of the asyncio event loop used to execute async fixtures", + default=None, + ) @overload @@ -189,8 +195,20 @@ def _get_asyncio_mode(config: Config) -> Mode: ) +_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 pytest_configure(config: Config) -> None: - """Inject documentation.""" + default_loop_scope = config.getini("asyncio_default_fixture_loop_scope") + if not default_loop_scope: + warnings.warn(PytestDeprecationWarning(_DEFAULT_FIXTURE_LOOP_SCOPE_UNSET)) config.addinivalue_line( "markers", "asyncio: " @@ -203,7 +221,8 @@ def pytest_configure(config: Config) -> None: def pytest_report_header(config: Config) -> List[str]: """Add asyncio config to pytest header.""" mode = _get_asyncio_mode(config) - return [f"asyncio: mode={mode}"] + default_loop_scope = config.getini("asyncio_default_fixture_loop_scope") + return [f"asyncio: mode={mode}, default_loop_scope={default_loop_scope}"] def _preprocess_async_fixtures( @@ -211,6 +230,7 @@ def _preprocess_async_fixtures( processed_fixturedefs: Set[FixtureDef], ) -> None: config = collector.config + default_loop_scope = config.getini("asyncio_default_fixture_loop_scope") asyncio_mode = _get_asyncio_mode(config) fixturemanager = config.pluginmanager.get_plugin("funcmanage") assert fixturemanager is not None @@ -225,7 +245,11 @@ def _preprocess_async_fixtures( # Ignore async fixtures without explicit asyncio mark in strict mode # This applies to pytest_trio fixtures, for example continue - scope = getattr(func, "_loop_scope", None) or fixturedef.scope + scope = ( + getattr(func, "_loop_scope", None) + or default_loop_scope + or fixturedef.scope + ) if scope == "function": event_loop_fixture_id: Optional[str] = "event_loop" else: diff --git a/tests/test_fixture_loop_scopes.py b/tests/test_fixture_loop_scopes.py index 1f4d0a35..737a5573 100644 --- a/tests/test_fixture_loop_scopes.py +++ b/tests/test_fixture_loop_scopes.py @@ -34,3 +34,103 @@ async def test_runs_in_same_loop_as_fixture(fixture): ) result = pytester.runpytest_subprocess("--asyncio-mode=strict") result.assert_outcomes(passed=1) + + +@pytest.mark.parametrize("default_loop_scope", ("function", "module", "session")) +def test_default_loop_scope_config_option_changes_fixture_loop_scope( + pytester: Pytester, + default_loop_scope: str, +): + pytester.makeini( + dedent( + f"""\ + [pytest] + asyncio_default_fixture_loop_scope = {default_loop_scope} + """ + ) + ) + pytester.makepyfile( + dedent( + f"""\ + import asyncio + import pytest + import pytest_asyncio + + @pytest_asyncio.fixture + async def fixture_loop(): + return asyncio.get_running_loop() + + @pytest.mark.asyncio(scope="{default_loop_scope}") + async def test_runs_in_fixture_loop(fixture_loop): + assert asyncio.get_running_loop() is fixture_loop + """ + ) + ) + result = pytester.runpytest_subprocess("--asyncio-mode=strict") + result.assert_outcomes(passed=1) + + +def test_default_class_loop_scope_config_option_changes_fixture_loop_scope( + pytester: Pytester, +): + pytester.makeini( + dedent( + """\ + [pytest] + asyncio_default_fixture_loop_scope = class + """ + ) + ) + pytester.makepyfile( + dedent( + """\ + import asyncio + import pytest + import pytest_asyncio + + class TestClass: + @pytest_asyncio.fixture + async def fixture_loop(self): + return asyncio.get_running_loop() + + @pytest.mark.asyncio(scope="class") + async def test_runs_in_fixture_loop(self, fixture_loop): + assert asyncio.get_running_loop() is fixture_loop + """ + ) + ) + result = pytester.runpytest_subprocess("--asyncio-mode=strict") + result.assert_outcomes(passed=1) + + +def test_default_package_loop_scope_config_option_changes_fixture_loop_scope( + pytester: Pytester, +): + pytester.makeini( + dedent( + """\ + [pytest] + asyncio_default_fixture_loop_scope = package + """ + ) + ) + pytester.makepyfile( + __init__="", + test_a=dedent( + """\ + import asyncio + import pytest + import pytest_asyncio + + @pytest_asyncio.fixture + async def fixture_loop(): + return asyncio.get_running_loop() + + @pytest.mark.asyncio(scope="package") + async def test_runs_in_fixture_loop(fixture_loop): + assert asyncio.get_running_loop() is fixture_loop + """ + ), + ) + result = pytester.runpytest_subprocess("--asyncio-mode=strict") + result.assert_outcomes(passed=1) From 03e141413734a9f602493b74831e3689942c0a80 Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Fri, 12 Jul 2024 13:21:45 +0200 Subject: [PATCH 017/226] refactor: Extracted function that returns the event loop scope of a marked function. --- pytest_asyncio/plugin.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/pytest_asyncio/plugin.py b/pytest_asyncio/plugin.py index d7618c1b..766cfff8 100644 --- a/pytest_asyncio/plugin.py +++ b/pytest_asyncio/plugin.py @@ -38,6 +38,7 @@ FixtureRequest, Function, Item, + Mark, Metafunc, Module, Package, @@ -738,7 +739,7 @@ def pytest_generate_tests(metafunc: Metafunc) -> None: marker = metafunc.definition.get_closest_marker("asyncio") if not marker: return - scope = marker.kwargs.get("scope", "function") + scope = _get_marked_loop_scope(marker) if scope == "function": return event_loop_node = _retrieve_scope_root(metafunc.definition, scope) @@ -971,7 +972,7 @@ def pytest_runtest_setup(item: pytest.Item) -> None: marker = item.get_closest_marker("asyncio") if marker is None: return - scope = marker.kwargs.get("scope", "function") + scope = _get_marked_loop_scope(marker) if scope != "function": parent_node = _retrieve_scope_root(item, scope) event_loop_fixture_id = parent_node.stash[_event_loop_fixture_id] @@ -990,6 +991,11 @@ def pytest_runtest_setup(item: pytest.Item) -> None: ) +def _get_marked_loop_scope(asyncio_marker: Mark) -> _ScopeName: + assert asyncio_marker.name == "asyncio" + return asyncio_marker.kwargs.get("scope", "function") + + def _retrieve_scope_root(item: Union[Collector, Item], scope: str) -> Collector: node_type_by_scope = { "class": Class, From 85c15174d869c014e3c139e580758f310365d04e Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Fri, 12 Jul 2024 13:49:36 +0200 Subject: [PATCH 018/226] feat: Allow use of "loop_scope" kwarg in asyncio markers. --- pytest_asyncio/plugin.py | 14 +++++++++- tests/markers/test_function_scope.py | 41 ++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/pytest_asyncio/plugin.py b/pytest_asyncio/plugin.py index 766cfff8..e8f6d4d8 100644 --- a/pytest_asyncio/plugin.py +++ b/pytest_asyncio/plugin.py @@ -991,9 +991,21 @@ def pytest_runtest_setup(item: pytest.Item) -> None: ) +_DUPLICATE_LOOP_SCOPE_DEFINITION_ERROR = """\ +An asyncio pytest marker defines both "scope" and "loop_scope", \ +but it should only use "loop_scope". +""" + + def _get_marked_loop_scope(asyncio_marker: Mark) -> _ScopeName: assert asyncio_marker.name == "asyncio" - return asyncio_marker.kwargs.get("scope", "function") + if "scope" in asyncio_marker.kwargs and "loop_scope" in asyncio_marker.kwargs: + raise pytest.UsageError(_DUPLICATE_LOOP_SCOPE_DEFINITION_ERROR) + scope = asyncio_marker.kwargs.get("loop_scope") or asyncio_marker.kwargs.get( + "scope", "function" + ) + assert scope in {"function", "class", "module", "package", "session"} + return scope def _retrieve_scope_root(item: Union[Collector, Item], scope: str) -> Collector: diff --git a/tests/markers/test_function_scope.py b/tests/markers/test_function_scope.py index eded4552..35771d93 100644 --- a/tests/markers/test_function_scope.py +++ b/tests/markers/test_function_scope.py @@ -28,6 +28,47 @@ async def test_does_not_run_in_same_loop(): result.assert_outcomes(passed=2) +def test_loop_scope_function_provides_function_scoped_event_loop(pytester: Pytester): + pytester.makepyfile( + dedent( + """\ + import asyncio + import pytest + + pytestmark = pytest.mark.asyncio(loop_scope="function") + + loop: asyncio.AbstractEventLoop + + async def test_remember_loop(): + global loop + loop = asyncio.get_running_loop() + + async def test_does_not_run_in_same_loop(): + global loop + assert asyncio.get_running_loop() is not loop + """ + ) + ) + result = pytester.runpytest("--asyncio-mode=strict") + result.assert_outcomes(passed=2) + + +def test_raises_when_scope_and_loop_scope_arguments_are_present(pytester: Pytester): + pytester.makepyfile( + dedent( + """\ + import pytest + + @pytest.mark.asyncio(scope="function", loop_scope="function") + async def test_raises(): + ... + """ + ) + ) + result = pytester.runpytest("--asyncio-mode=strict") + result.assert_outcomes(errors=1) + + def test_function_scope_supports_explicit_event_loop_fixture_request( pytester: Pytester, ): From a40333af0149cdd89f232e9002165ef678126185 Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Sat, 13 Jul 2024 15:24:08 +0200 Subject: [PATCH 019/226] [feat] Deprecates the optional `scope` keyword argument of asyncio markers. Users are encouraged to use the `loop_scope` keyword argument. The `loop_scope` kwarg does exactly the same, though its naming is consistent with the `loop_scope` kwarg of ``pytest_asyncio.fixture``. Signed-off-by: Michael Seifert --- docs/source/concepts.rst | 2 +- docs/source/concepts_module_scope_example.py | 4 +-- .../class_scoped_loop_example.py | 2 +- .../module_scoped_loop_example.py | 2 +- .../package_scoped_loop_example.py | 2 +- .../run_class_tests_in_same_loop.rst | 2 +- .../run_module_tests_in_same_loop.rst | 2 +- .../run_package_tests_in_same_loop.rst | 2 +- .../run_session_tests_in_same_loop.rst | 2 +- .../session_scoped_loop_example.py | 2 +- docs/source/reference/changelog.rst | 5 ++++ .../fixtures/event_loop_policy_example.py | 2 +- .../class_scoped_loop_strict_mode_example.py | 2 +- ...d_loop_with_fixture_strict_mode_example.py | 2 +- docs/source/reference/markers/index.rst | 2 +- .../module_scoped_loop_strict_mode_example.py | 2 +- pytest_asyncio/plugin.py | 11 ++++++-- .../test_async_fixtures_with_finalizer.py | 4 +-- tests/markers/test_class_scope.py | 20 +++++++------- tests/markers/test_function_scope.py | 17 ++++++++++++ tests/markers/test_module_scope.py | 22 ++++++++-------- tests/markers/test_package_scope.py | 24 ++++++++--------- tests/markers/test_session_scope.py | 26 +++++++++---------- tests/test_fixture_loop_scopes.py | 8 +++--- 24 files changed, 99 insertions(+), 70 deletions(-) diff --git a/docs/source/concepts.rst b/docs/source/concepts.rst index 710c5365..298d08f2 100644 --- a/docs/source/concepts.rst +++ b/docs/source/concepts.rst @@ -32,7 +32,7 @@ You may notice that the individual levels resemble the possible `scopes of a pyt Pytest-asyncio provides one asyncio event loop for each pytest collector. By default, each test runs in the event loop provided by the *Function* collector, i.e. tests use the loop with the narrowest scope. This gives the highest level of isolation between tests. -If two or more tests share a common ancestor collector, the tests can be configured to run in their ancestor's loop by passing the appropriate *scope* keyword argument to the *asyncio* mark. +If two or more tests share a common ancestor collector, the tests can be configured to run in their ancestor's loop by passing the appropriate *loop_scope* keyword argument to the *asyncio* mark. For example, the following two tests use the asyncio event loop provided by the *Module* collector: .. include:: concepts_module_scope_example.py diff --git a/docs/source/concepts_module_scope_example.py b/docs/source/concepts_module_scope_example.py index 66972888..b83181b4 100644 --- a/docs/source/concepts_module_scope_example.py +++ b/docs/source/concepts_module_scope_example.py @@ -5,13 +5,13 @@ loop: asyncio.AbstractEventLoop -@pytest.mark.asyncio(scope="module") +@pytest.mark.asyncio(loop_scope="module") async def test_remember_loop(): global loop loop = asyncio.get_running_loop() -@pytest.mark.asyncio(scope="module") +@pytest.mark.asyncio(loop_scope="module") async def test_runs_in_a_loop(): global loop assert asyncio.get_running_loop() is loop diff --git a/docs/source/how-to-guides/class_scoped_loop_example.py b/docs/source/how-to-guides/class_scoped_loop_example.py index 5419a7ab..7ffc4b1f 100644 --- a/docs/source/how-to-guides/class_scoped_loop_example.py +++ b/docs/source/how-to-guides/class_scoped_loop_example.py @@ -3,7 +3,7 @@ import pytest -@pytest.mark.asyncio(scope="class") +@pytest.mark.asyncio(loop_scope="class") class TestInOneEventLoopPerClass: loop: asyncio.AbstractEventLoop diff --git a/docs/source/how-to-guides/module_scoped_loop_example.py b/docs/source/how-to-guides/module_scoped_loop_example.py index b4ef778c..38ba8bdc 100644 --- a/docs/source/how-to-guides/module_scoped_loop_example.py +++ b/docs/source/how-to-guides/module_scoped_loop_example.py @@ -2,7 +2,7 @@ import pytest -pytestmark = pytest.mark.asyncio(scope="module") +pytestmark = pytest.mark.asyncio(loop_scope="module") loop: asyncio.AbstractEventLoop diff --git a/docs/source/how-to-guides/package_scoped_loop_example.py b/docs/source/how-to-guides/package_scoped_loop_example.py index f48c33f1..903e9c8c 100644 --- a/docs/source/how-to-guides/package_scoped_loop_example.py +++ b/docs/source/how-to-guides/package_scoped_loop_example.py @@ -1,3 +1,3 @@ import pytest -pytestmark = pytest.mark.asyncio(scope="package") +pytestmark = pytest.mark.asyncio(loop_scope="package") diff --git a/docs/source/how-to-guides/run_class_tests_in_same_loop.rst b/docs/source/how-to-guides/run_class_tests_in_same_loop.rst index a265899c..2ba40683 100644 --- a/docs/source/how-to-guides/run_class_tests_in_same_loop.rst +++ b/docs/source/how-to-guides/run_class_tests_in_same_loop.rst @@ -1,7 +1,7 @@ ====================================================== How to run all tests in a class in the same event loop ====================================================== -All tests can be run inside the same event loop by marking them with ``pytest.mark.asyncio(scope="class")``. +All tests can be run inside the same event loop by marking them with ``pytest.mark.asyncio(loop_scope="class")``. This is easily achieved by using the *asyncio* marker as a class decorator. .. include:: class_scoped_loop_example.py diff --git a/docs/source/how-to-guides/run_module_tests_in_same_loop.rst b/docs/source/how-to-guides/run_module_tests_in_same_loop.rst index e07eca2e..c07de737 100644 --- a/docs/source/how-to-guides/run_module_tests_in_same_loop.rst +++ b/docs/source/how-to-guides/run_module_tests_in_same_loop.rst @@ -1,7 +1,7 @@ ======================================================= How to run all tests in a module in the same event loop ======================================================= -All tests can be run inside the same event loop by marking them with ``pytest.mark.asyncio(scope="module")``. +All tests can be run inside the same event loop by marking them with ``pytest.mark.asyncio(loop_scope="module")``. This is easily achieved by adding a `pytestmark` statement to your module. .. include:: module_scoped_loop_example.py diff --git a/docs/source/how-to-guides/run_package_tests_in_same_loop.rst b/docs/source/how-to-guides/run_package_tests_in_same_loop.rst index 24326ed1..0392693f 100644 --- a/docs/source/how-to-guides/run_package_tests_in_same_loop.rst +++ b/docs/source/how-to-guides/run_package_tests_in_same_loop.rst @@ -1,7 +1,7 @@ ======================================================== How to run all tests in a package in the same event loop ======================================================== -All tests can be run inside the same event loop by marking them with ``pytest.mark.asyncio(scope="package")``. +All tests can be run inside the same event loop by marking them with ``pytest.mark.asyncio(loop_scope="package")``. Add the following code to the ``__init__.py`` of the test package: .. include:: package_scoped_loop_example.py diff --git a/docs/source/how-to-guides/run_session_tests_in_same_loop.rst b/docs/source/how-to-guides/run_session_tests_in_same_loop.rst index 75bcd71e..f166fea0 100644 --- a/docs/source/how-to-guides/run_session_tests_in_same_loop.rst +++ b/docs/source/how-to-guides/run_session_tests_in_same_loop.rst @@ -1,7 +1,7 @@ ========================================================== How to run all tests in the session in the same event loop ========================================================== -All tests can be run inside the same event loop by marking them with ``pytest.mark.asyncio(scope="session")``. +All tests can be run inside the same event loop by marking them with ``pytest.mark.asyncio(loop_scope="session")``. The easiest way to mark all tests is via a ``pytest_collection_modifyitems`` hook in the ``conftest.py`` at the root folder of your test suite. .. include:: session_scoped_loop_example.py diff --git a/docs/source/how-to-guides/session_scoped_loop_example.py b/docs/source/how-to-guides/session_scoped_loop_example.py index 5d877116..79cc8676 100644 --- a/docs/source/how-to-guides/session_scoped_loop_example.py +++ b/docs/source/how-to-guides/session_scoped_loop_example.py @@ -5,6 +5,6 @@ def pytest_collection_modifyitems(items): pytest_asyncio_tests = (item for item in items if is_async_test(item)) - session_scope_marker = pytest.mark.asyncio(scope="session") + session_scope_marker = pytest.mark.asyncio(loop_scope="session") for async_test in pytest_asyncio_tests: async_test.add_marker(session_scope_marker, append=False) diff --git a/docs/source/reference/changelog.rst b/docs/source/reference/changelog.rst index b62e5114..9c58ae44 100644 --- a/docs/source/reference/changelog.rst +++ b/docs/source/reference/changelog.rst @@ -2,6 +2,11 @@ Changelog ========= +0.24.0 (UNRELEASED) +=================== +- Deprecates the optional `scope` keyword argument of asyncio markers. Users are encouraged to use the `loop_scope` keyword argument. The `loop_scope` kwarg does exactly the same, though its naming is consistent with the `loop_scope` kwarg of ``pytest_asyncio.fixture``. + + 0.23.8 (2024-07-17) =================== - Fixes a bug that caused duplicate markers in async tests `#813 `_ diff --git a/docs/source/reference/fixtures/event_loop_policy_example.py b/docs/source/reference/fixtures/event_loop_policy_example.py index cfd7ab96..5fd87b73 100644 --- a/docs/source/reference/fixtures/event_loop_policy_example.py +++ b/docs/source/reference/fixtures/event_loop_policy_example.py @@ -12,6 +12,6 @@ def event_loop_policy(request): return CustomEventLoopPolicy() -@pytest.mark.asyncio(scope="module") +@pytest.mark.asyncio(loop_scope="module") async def test_uses_custom_event_loop_policy(): assert isinstance(asyncio.get_event_loop_policy(), CustomEventLoopPolicy) diff --git a/docs/source/reference/markers/class_scoped_loop_strict_mode_example.py b/docs/source/reference/markers/class_scoped_loop_strict_mode_example.py index 38b5689c..e75279d5 100644 --- a/docs/source/reference/markers/class_scoped_loop_strict_mode_example.py +++ b/docs/source/reference/markers/class_scoped_loop_strict_mode_example.py @@ -3,7 +3,7 @@ import pytest -@pytest.mark.asyncio(scope="class") +@pytest.mark.asyncio(loop_scope="class") class TestClassScopedLoop: loop: asyncio.AbstractEventLoop diff --git a/docs/source/reference/markers/class_scoped_loop_with_fixture_strict_mode_example.py b/docs/source/reference/markers/class_scoped_loop_with_fixture_strict_mode_example.py index 538f1bd2..239f3968 100644 --- a/docs/source/reference/markers/class_scoped_loop_with_fixture_strict_mode_example.py +++ b/docs/source/reference/markers/class_scoped_loop_with_fixture_strict_mode_example.py @@ -5,7 +5,7 @@ import pytest_asyncio -@pytest.mark.asyncio(scope="class") +@pytest.mark.asyncio(loop_scope="class") class TestClassScopedLoop: loop: asyncio.AbstractEventLoop diff --git a/docs/source/reference/markers/index.rst b/docs/source/reference/markers/index.rst index a875b90d..6e9be1ca 100644 --- a/docs/source/reference/markers/index.rst +++ b/docs/source/reference/markers/index.rst @@ -18,7 +18,7 @@ Multiple async tests in a single class or module can be marked using |pytestmark The ``pytest.mark.asyncio`` marker can be omitted entirely in |auto mode|_ where the *asyncio* marker is added automatically to *async* test functions. By default, each test runs in it's own asyncio event loop. -Multiple tests can share the same event loop by providing a *scope* keyword argument to the *asyncio* mark. +Multiple tests can share the same event loop by providing a *loop_scope* keyword argument to the *asyncio* mark. The supported scopes are *class,* and *module,* and *package*. The following code example provides a shared event loop for all tests in `TestClassScopedLoop`: diff --git a/docs/source/reference/markers/module_scoped_loop_strict_mode_example.py b/docs/source/reference/markers/module_scoped_loop_strict_mode_example.py index 221d554e..cece90db 100644 --- a/docs/source/reference/markers/module_scoped_loop_strict_mode_example.py +++ b/docs/source/reference/markers/module_scoped_loop_strict_mode_example.py @@ -2,7 +2,7 @@ import pytest -pytestmark = pytest.mark.asyncio(scope="module") +pytestmark = pytest.mark.asyncio(loop_scope="module") loop: asyncio.AbstractEventLoop diff --git a/pytest_asyncio/plugin.py b/pytest_asyncio/plugin.py index e8f6d4d8..aaa1e8f3 100644 --- a/pytest_asyncio/plugin.py +++ b/pytest_asyncio/plugin.py @@ -996,11 +996,18 @@ def pytest_runtest_setup(item: pytest.Item) -> None: but it should only use "loop_scope". """ +_MARKER_SCOPE_KWARG_DEPRECATION_WARNING = """\ +The "scope" keyword argument to the asyncio marker has been deprecated. \ +Please use the "loop_scope" argument instead. +""" + def _get_marked_loop_scope(asyncio_marker: Mark) -> _ScopeName: assert asyncio_marker.name == "asyncio" - if "scope" in asyncio_marker.kwargs and "loop_scope" in asyncio_marker.kwargs: - raise pytest.UsageError(_DUPLICATE_LOOP_SCOPE_DEFINITION_ERROR) + if "scope" in asyncio_marker.kwargs: + if "loop_scope" in asyncio_marker.kwargs: + raise pytest.UsageError(_DUPLICATE_LOOP_SCOPE_DEFINITION_ERROR) + warnings.warn(PytestDeprecationWarning(_MARKER_SCOPE_KWARG_DEPRECATION_WARNING)) scope = asyncio_marker.kwargs.get("loop_scope") or asyncio_marker.kwargs.get( "scope", "function" ) diff --git a/tests/async_fixtures/test_async_fixtures_with_finalizer.py b/tests/async_fixtures/test_async_fixtures_with_finalizer.py index b4d2ac94..bc6826bb 100644 --- a/tests/async_fixtures/test_async_fixtures_with_finalizer.py +++ b/tests/async_fixtures/test_async_fixtures_with_finalizer.py @@ -4,13 +4,13 @@ import pytest -@pytest.mark.asyncio(scope="module") +@pytest.mark.asyncio(loop_scope="module") async def test_module_with_event_loop_finalizer(port_with_event_loop_finalizer): await asyncio.sleep(0.01) assert port_with_event_loop_finalizer -@pytest.mark.asyncio(scope="module") +@pytest.mark.asyncio(loop_scope="module") async def test_module_with_get_event_loop_finalizer(port_with_get_event_loop_finalizer): await asyncio.sleep(0.01) assert port_with_get_event_loop_finalizer diff --git a/tests/markers/test_class_scope.py b/tests/markers/test_class_scope.py index 3c77bab0..baac5869 100644 --- a/tests/markers/test_class_scope.py +++ b/tests/markers/test_class_scope.py @@ -39,11 +39,11 @@ def test_asyncio_mark_provides_class_scoped_loop_when_applied_to_functions( class TestClassScopedLoop: loop: asyncio.AbstractEventLoop - @pytest.mark.asyncio(scope="class") + @pytest.mark.asyncio(loop_scope="class") async def test_remember_loop(self): TestClassScopedLoop.loop = asyncio.get_running_loop() - @pytest.mark.asyncio(scope="class") + @pytest.mark.asyncio(loop_scope="class") async def test_this_runs_in_same_loop(self): assert asyncio.get_running_loop() is TestClassScopedLoop.loop """ @@ -62,7 +62,7 @@ def test_asyncio_mark_provides_class_scoped_loop_when_applied_to_class( import asyncio import pytest - @pytest.mark.asyncio(scope="class") + @pytest.mark.asyncio(loop_scope="class") class TestClassScopedLoop: loop: asyncio.AbstractEventLoop @@ -87,7 +87,7 @@ def test_asyncio_mark_raises_when_class_scoped_is_request_without_class( import asyncio import pytest - @pytest.mark.asyncio(scope="class") + @pytest.mark.asyncio(loop_scope="class") async def test_has_no_surrounding_class(): pass """ @@ -107,7 +107,7 @@ def test_asyncio_mark_is_inherited_to_subclasses(pytester: pytest.Pytester): import asyncio import pytest - @pytest.mark.asyncio(scope="class") + @pytest.mark.asyncio(loop_scope="class") class TestSuperClassWithMark: pass @@ -183,7 +183,7 @@ def test_asyncio_mark_respects_parametrized_loop_policies( def event_loop_policy(request): return request.param - @pytest.mark.asyncio(scope="class") + @pytest.mark.asyncio(loop_scope="class") class TestWithDifferentLoopPolicies: async def test_parametrized_loop(self, request): pass @@ -205,7 +205,7 @@ def test_asyncio_mark_provides_class_scoped_loop_to_fixtures( import pytest import pytest_asyncio - @pytest.mark.asyncio(scope="class") + @pytest.mark.asyncio(loop_scope="class") class TestClassScopedLoop: loop: asyncio.AbstractEventLoop @@ -242,7 +242,7 @@ async def async_fixture(self): global loop loop = asyncio.get_running_loop() - @pytest.mark.asyncio(scope="function") + @pytest.mark.asyncio(loop_scope="function") async def test_runs_in_different_loop_as_fixture(self, async_fixture): global loop assert asyncio.get_running_loop() is not loop @@ -277,7 +277,7 @@ def sets_event_loop_to_none(self): return asyncio.run(asyncio.sleep(0)) # asyncio.run() sets the current event loop to None when finished - @pytest.mark.asyncio(scope="class") + @pytest.mark.asyncio(loop_scope="class") # parametrization may impact fixture ordering @pytest.mark.parametrize("n", (0, 1)) async def test_does_not_fail(self, sets_event_loop_to_none, n): @@ -297,7 +297,7 @@ def test_standalone_test_does_not_trigger_warning_about_no_current_event_loop_be """\ import pytest - @pytest.mark.asyncio(scope="class") + @pytest.mark.asyncio(loop_scope="class") class TestClass: async def test_anything(self): pass diff --git a/tests/markers/test_function_scope.py b/tests/markers/test_function_scope.py index 35771d93..81260006 100644 --- a/tests/markers/test_function_scope.py +++ b/tests/markers/test_function_scope.py @@ -69,6 +69,23 @@ async def test_raises(): result.assert_outcomes(errors=1) +def test_warns_when_scope_argument_is_present(pytester: Pytester): + pytester.makepyfile( + dedent( + """\ + import pytest + + @pytest.mark.asyncio(scope="function") + async def test_warns(): + ... + """ + ) + ) + result = pytester.runpytest_subprocess("--asyncio-mode=strict") + result.assert_outcomes(passed=1, warnings=2) + result.stdout.fnmatch_lines("*DeprecationWarning*") + + def test_function_scope_supports_explicit_event_loop_fixture_request( pytester: Pytester, ): diff --git a/tests/markers/test_module_scope.py b/tests/markers/test_module_scope.py index 5cc6a2a7..5280ed7e 100644 --- a/tests/markers/test_module_scope.py +++ b/tests/markers/test_module_scope.py @@ -62,7 +62,7 @@ def test_asyncio_mark_provides_module_scoped_loop_strict_mode(pytester: Pytester import asyncio import pytest - pytestmark = pytest.mark.asyncio(scope="module") + pytestmark = pytest.mark.asyncio(loop_scope="module") loop: asyncio.AbstractEventLoop @@ -94,7 +94,7 @@ def test_raise_when_event_loop_fixture_is_requested_in_addition_to_scoped_loop( import asyncio import pytest - pytestmark = pytest.mark.asyncio(scope="module") + pytestmark = pytest.mark.asyncio(loop_scope="module") async def test_remember_loop(event_loop): pass @@ -126,7 +126,7 @@ class CustomEventLoopPolicy(asyncio.DefaultEventLoopPolicy): from .custom_policy import CustomEventLoopPolicy - pytestmark = pytest.mark.asyncio(scope="module") + pytestmark = pytest.mark.asyncio(loop_scope="module") @pytest.fixture(scope="module") def event_loop_policy(): @@ -146,7 +146,7 @@ async def test_uses_custom_event_loop_policy(): from .custom_policy import CustomEventLoopPolicy - pytestmark = pytest.mark.asyncio(scope="module") + pytestmark = pytest.mark.asyncio(loop_scope="module") async def test_does_not_use_custom_event_loop_policy(): assert not isinstance( @@ -170,7 +170,7 @@ def test_asyncio_mark_respects_parametrized_loop_policies( import pytest - pytestmark = pytest.mark.asyncio(scope="module") + pytestmark = pytest.mark.asyncio(loop_scope="module") @pytest.fixture( scope="module", @@ -202,7 +202,7 @@ def test_asyncio_mark_provides_module_scoped_loop_to_fixtures( import pytest import pytest_asyncio - pytestmark = pytest.mark.asyncio(scope="module") + pytestmark = pytest.mark.asyncio(loop_scope="module") loop: asyncio.AbstractEventLoop @@ -239,7 +239,7 @@ async def async_fixture(): global loop loop = asyncio.get_running_loop() - @pytest.mark.asyncio(scope="class") + @pytest.mark.asyncio(loop_scope="class") class TestMixedScopes: async def test_runs_in_different_loop_as_fixture(self, async_fixture): global loop @@ -271,7 +271,7 @@ async def async_fixture(): global loop loop = asyncio.get_running_loop() - @pytest.mark.asyncio(scope="function") + @pytest.mark.asyncio(loop_scope="function") async def test_runs_in_different_loop_as_fixture(async_fixture): global loop assert asyncio.get_running_loop() is not loop @@ -301,7 +301,7 @@ async def async_fixture(): loop = asyncio.get_running_loop() yield - @pytest.mark.asyncio(scope="function") + @pytest.mark.asyncio(loop_scope="function") async def test_runs_in_different_loop_as_fixture(async_fixture): global loop assert asyncio.get_running_loop() is not loop @@ -334,7 +334,7 @@ def sets_event_loop_to_none(): return asyncio.run(asyncio.sleep(0)) # asyncio.run() sets the current event loop to None when finished - @pytest.mark.asyncio(scope="module") + @pytest.mark.asyncio(loop_scope="module") # parametrization may impact fixture ordering @pytest.mark.parametrize("n", (0, 1)) async def test_does_not_fail(sets_event_loop_to_none, n): @@ -354,7 +354,7 @@ def test_standalone_test_does_not_trigger_warning_about_no_current_event_loop_be """\ import pytest - @pytest.mark.asyncio(scope="module") + @pytest.mark.asyncio(loop_scope="module") async def test_anything(): pass """ diff --git a/tests/markers/test_package_scope.py b/tests/markers/test_package_scope.py index c80289be..849967e8 100644 --- a/tests/markers/test_package_scope.py +++ b/tests/markers/test_package_scope.py @@ -22,7 +22,7 @@ def test_asyncio_mark_provides_package_scoped_loop_strict_mode(pytester: Pyteste from {package_name} import shared_module - @pytest.mark.asyncio(scope="package") + @pytest.mark.asyncio(loop_scope="package") async def test_remember_loop(): shared_module.loop = asyncio.get_running_loop() """ @@ -34,7 +34,7 @@ async def test_remember_loop(): from {package_name} import shared_module - pytestmark = pytest.mark.asyncio(scope="package") + pytestmark = pytest.mark.asyncio(loop_scope="package") async def test_this_runs_in_same_loop(): assert asyncio.get_running_loop() is shared_module.loop @@ -55,7 +55,7 @@ async def test_this_runs_in_same_loop(self): from {package_name} import shared_module - pytestmark = pytest.mark.asyncio(scope="package") + pytestmark = pytest.mark.asyncio(loop_scope="package") async def test_subpackage_runs_in_different_loop(): assert asyncio.get_running_loop() is not shared_module.loop @@ -76,7 +76,7 @@ def test_raise_when_event_loop_fixture_is_requested_in_addition_to_scoped_loop( import asyncio import pytest - @pytest.mark.asyncio(scope="package") + @pytest.mark.asyncio(loop_scope="package") async def test_remember_loop(event_loop): pass """ @@ -118,7 +118,7 @@ class CustomEventLoopPolicy(asyncio.DefaultEventLoopPolicy): from .custom_policy import CustomEventLoopPolicy - pytestmark = pytest.mark.asyncio(scope="package") + pytestmark = pytest.mark.asyncio(loop_scope="package") async def test_uses_custom_event_loop_policy(): assert isinstance( @@ -134,7 +134,7 @@ async def test_uses_custom_event_loop_policy(): from .custom_policy import CustomEventLoopPolicy - pytestmark = pytest.mark.asyncio(scope="package") + pytestmark = pytest.mark.asyncio(loop_scope="package") async def test_also_uses_custom_event_loop_policy(): assert isinstance( @@ -159,7 +159,7 @@ def test_asyncio_mark_respects_parametrized_loop_policies( import pytest - pytestmark = pytest.mark.asyncio(scope="package") + pytestmark = pytest.mark.asyncio(loop_scope="package") @pytest.fixture( scope="package", @@ -215,7 +215,7 @@ async def my_fixture(): from {package_name} import shared_module - pytestmark = pytest.mark.asyncio(scope="package") + pytestmark = pytest.mark.asyncio(loop_scope="package") async def test_runs_in_same_loop_as_fixture(my_fixture): assert asyncio.get_running_loop() is shared_module.loop @@ -245,7 +245,7 @@ async def async_fixture(): global loop loop = asyncio.get_running_loop() - @pytest.mark.asyncio(scope="module") + @pytest.mark.asyncio(loop_scope="module") async def test_runs_in_different_loop_as_fixture(async_fixture): global loop assert asyncio.get_running_loop() is not loop @@ -275,7 +275,7 @@ async def async_fixture(): global loop loop = asyncio.get_running_loop() - @pytest.mark.asyncio(scope="class") + @pytest.mark.asyncio(loop_scope="class") class TestMixedScopes: async def test_runs_in_different_loop_as_fixture(self, async_fixture): global loop @@ -340,7 +340,7 @@ def sets_event_loop_to_none(): return asyncio.run(asyncio.sleep(0)) # asyncio.run() sets the current event loop to None when finished - @pytest.mark.asyncio(scope="package") + @pytest.mark.asyncio(loop_scope="package") # parametrization may impact fixture ordering @pytest.mark.parametrize("n", (0, 1)) async def test_does_not_fail(sets_event_loop_to_none, n): @@ -361,7 +361,7 @@ def test_standalone_test_does_not_trigger_warning_about_no_current_event_loop_be """\ import pytest - @pytest.mark.asyncio(scope="package") + @pytest.mark.asyncio(loop_scope="package") async def test_anything(): pass """ diff --git a/tests/markers/test_session_scope.py b/tests/markers/test_session_scope.py index b8b747a0..7900ef48 100644 --- a/tests/markers/test_session_scope.py +++ b/tests/markers/test_session_scope.py @@ -21,7 +21,7 @@ def test_asyncio_mark_provides_session_scoped_loop_strict_mode(pytester: Pyteste from {package_name} import shared_module - @pytest.mark.asyncio(scope="session") + @pytest.mark.asyncio(loop_scope="session") async def test_remember_loop(): shared_module.loop = asyncio.get_running_loop() """ @@ -33,7 +33,7 @@ async def test_remember_loop(): from {package_name} import shared_module - pytestmark = pytest.mark.asyncio(scope="session") + pytestmark = pytest.mark.asyncio(loop_scope="session") async def test_this_runs_in_same_loop(): assert asyncio.get_running_loop() is shared_module.loop @@ -56,7 +56,7 @@ async def test_this_runs_in_same_loop(self): from {package_name} import shared_module - pytestmark = pytest.mark.asyncio(scope="session") + pytestmark = pytest.mark.asyncio(loop_scope="session") async def test_subpackage_runs_in_same_loop(): assert asyncio.get_running_loop() is shared_module.loop @@ -77,7 +77,7 @@ def test_raise_when_event_loop_fixture_is_requested_in_addition_to_scoped_loop( import asyncio import pytest - @pytest.mark.asyncio(scope="session") + @pytest.mark.asyncio(loop_scope="session") async def test_remember_loop(event_loop): pass """ @@ -119,7 +119,7 @@ class CustomEventLoopPolicy(asyncio.DefaultEventLoopPolicy): from .custom_policy import CustomEventLoopPolicy - pytestmark = pytest.mark.asyncio(scope="session") + pytestmark = pytest.mark.asyncio(loop_scope="session") async def test_uses_custom_event_loop_policy(): assert isinstance( @@ -135,7 +135,7 @@ async def test_uses_custom_event_loop_policy(): from .custom_policy import CustomEventLoopPolicy - pytestmark = pytest.mark.asyncio(scope="session") + pytestmark = pytest.mark.asyncio(loop_scope="session") async def test_also_uses_custom_event_loop_policy(): assert isinstance( @@ -160,7 +160,7 @@ def test_asyncio_mark_respects_parametrized_loop_policies( import pytest - pytestmark = pytest.mark.asyncio(scope="session") + pytestmark = pytest.mark.asyncio(loop_scope="session") @pytest.fixture( scope="session", @@ -220,7 +220,7 @@ async def my_fixture(): from {package_name} import shared_module - pytestmark = pytest.mark.asyncio(scope="session") + pytestmark = pytest.mark.asyncio(loop_scope="session") async def test_runs_in_same_loop_as_fixture(my_fixture): assert asyncio.get_running_loop() is shared_module.loop @@ -250,7 +250,7 @@ async def async_fixture(): global loop loop = asyncio.get_running_loop() - @pytest.mark.asyncio(scope="package") + @pytest.mark.asyncio(loop_scope="package") async def test_runs_in_different_loop_as_fixture(async_fixture): global loop assert asyncio.get_running_loop() is not loop @@ -280,7 +280,7 @@ async def async_fixture(): global loop loop = asyncio.get_running_loop() - @pytest.mark.asyncio(scope="module") + @pytest.mark.asyncio(loop_scope="module") async def test_runs_in_different_loop_as_fixture(async_fixture): global loop assert asyncio.get_running_loop() is not loop @@ -310,7 +310,7 @@ async def async_fixture(): global loop loop = asyncio.get_running_loop() - @pytest.mark.asyncio(scope="class") + @pytest.mark.asyncio(loop_scope="class") class TestMixedScopes: async def test_runs_in_different_loop_as_fixture(self, async_fixture): global loop @@ -405,7 +405,7 @@ def sets_event_loop_to_none(): return asyncio.run(asyncio.sleep(0)) # asyncio.run() sets the current event loop to None when finished - @pytest.mark.asyncio(scope="session") + @pytest.mark.asyncio(loop_scope="session") # parametrization may impact fixture ordering @pytest.mark.parametrize("n", (0, 1)) async def test_does_not_fail(sets_event_loop_to_none, n): @@ -425,7 +425,7 @@ def test_standalone_test_does_not_trigger_warning_about_no_current_event_loop_be """\ import pytest - @pytest.mark.asyncio(scope="session") + @pytest.mark.asyncio(loop_scope="session") async def test_anything(): pass """ diff --git a/tests/test_fixture_loop_scopes.py b/tests/test_fixture_loop_scopes.py index 737a5573..f0271e59 100644 --- a/tests/test_fixture_loop_scopes.py +++ b/tests/test_fixture_loop_scopes.py @@ -25,7 +25,7 @@ async def fixture(): global loop loop = asyncio.get_running_loop() - @pytest.mark.asyncio(scope="session") + @pytest.mark.asyncio(loop_scope="session") async def test_runs_in_same_loop_as_fixture(fixture): global loop assert loop == asyncio.get_running_loop() @@ -60,7 +60,7 @@ def test_default_loop_scope_config_option_changes_fixture_loop_scope( async def fixture_loop(): return asyncio.get_running_loop() - @pytest.mark.asyncio(scope="{default_loop_scope}") + @pytest.mark.asyncio(loop_scope="{default_loop_scope}") async def test_runs_in_fixture_loop(fixture_loop): assert asyncio.get_running_loop() is fixture_loop """ @@ -93,7 +93,7 @@ class TestClass: async def fixture_loop(self): return asyncio.get_running_loop() - @pytest.mark.asyncio(scope="class") + @pytest.mark.asyncio(loop_scope="class") async def test_runs_in_fixture_loop(self, fixture_loop): assert asyncio.get_running_loop() is fixture_loop """ @@ -126,7 +126,7 @@ def test_default_package_loop_scope_config_option_changes_fixture_loop_scope( async def fixture_loop(): return asyncio.get_running_loop() - @pytest.mark.asyncio(scope="package") + @pytest.mark.asyncio(loop_scope="package") async def test_runs_in_fixture_loop(fixture_loop): assert asyncio.get_running_loop() is fixture_loop """ From d90ad955ca5c31d3ca3367ff60d1e3de620f16f3 Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Thu, 25 Jul 2024 08:18:26 +0200 Subject: [PATCH 020/226] docs: Added how-to guide on changing the event loop scope of a fixture. Signed-off-by: Michael Seifert --- docs/source/how-to-guides/change_fixture_loop.rst | 7 +++++++ .../how-to-guides/change_fixture_loop_example.py | 15 +++++++++++++++ docs/source/how-to-guides/index.rst | 1 + docs/source/reference/decorators/index.rst | 2 ++ 4 files changed, 25 insertions(+) create mode 100644 docs/source/how-to-guides/change_fixture_loop.rst create mode 100644 docs/source/how-to-guides/change_fixture_loop_example.py diff --git a/docs/source/how-to-guides/change_fixture_loop.rst b/docs/source/how-to-guides/change_fixture_loop.rst new file mode 100644 index 00000000..c6c8b8e6 --- /dev/null +++ b/docs/source/how-to-guides/change_fixture_loop.rst @@ -0,0 +1,7 @@ +=============================================== +How to change the event loop scope of a fixture +=============================================== +The event loop scope of an asynchronous fixture is specified via the *loop_scope* keyword argument to :ref:`pytest_asyncio.fixture `. The following fixture runs in the module-scoped event loop: + +.. include:: change_fixture_loop_example.py + :code: python diff --git a/docs/source/how-to-guides/change_fixture_loop_example.py b/docs/source/how-to-guides/change_fixture_loop_example.py new file mode 100644 index 00000000..dc6d2ef3 --- /dev/null +++ b/docs/source/how-to-guides/change_fixture_loop_example.py @@ -0,0 +1,15 @@ +import asyncio + +import pytest + +import pytest_asyncio + + +@pytest_asyncio.fixture(loop_scope="module") +async def current_loop(): + return asyncio.get_running_loop() + + +@pytest.mark.asyncio(loop_scope="module") +async def test_runs_in_module_loop(current_loop): + assert current_loop is asyncio.get_running_loop() diff --git a/docs/source/how-to-guides/index.rst b/docs/source/how-to-guides/index.rst index a61ead50..e47561d2 100644 --- a/docs/source/how-to-guides/index.rst +++ b/docs/source/how-to-guides/index.rst @@ -5,6 +5,7 @@ How-To Guides .. toctree:: :hidden: + change_fixture_loop run_class_tests_in_same_loop run_module_tests_in_same_loop run_package_tests_in_same_loop diff --git a/docs/source/reference/decorators/index.rst b/docs/source/reference/decorators/index.rst index 5c96cf4b..c049c5dd 100644 --- a/docs/source/reference/decorators/index.rst +++ b/docs/source/reference/decorators/index.rst @@ -1,3 +1,5 @@ +.. _decorators/pytest_asyncio_fixture: + ========== Decorators ========== From fe94cef1533664d8ea24a628d075cb73305f5b6c Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Thu, 25 Jul 2024 08:40:14 +0200 Subject: [PATCH 021/226] docs: Added how-to guide on changing the default event loop scope of all fixtures. Signed-off-by: Michael Seifert --- .../change_default_fixture_loop.rst | 24 +++++++++++++++++++ docs/source/how-to-guides/index.rst | 1 + docs/source/reference/configuration.rst | 2 ++ 3 files changed, 27 insertions(+) create mode 100644 docs/source/how-to-guides/change_default_fixture_loop.rst diff --git a/docs/source/how-to-guides/change_default_fixture_loop.rst b/docs/source/how-to-guides/change_default_fixture_loop.rst new file mode 100644 index 00000000..b54fef8e --- /dev/null +++ b/docs/source/how-to-guides/change_default_fixture_loop.rst @@ -0,0 +1,24 @@ +========================================================== +How to change the default event loop scope of all fixtures +========================================================== +The :ref:`configuration/asyncio_default_fixture_loop_scope` configuration option sets the default event loop scope for asynchronous fixtures. The following code snippets configure all fixtures to run in a session-scoped loop by default: + +.. code-block:: ini + :caption: pytest.ini + + [pytest] + asyncio_default_fixture_loop_scope = session + +.. code-block:: toml + :caption: pyproject.toml + + [tool.pytest.ini_options] + asyncio_default_fixture_loop_scope = "session" + +.. code-block:: ini + :caption: setup.cfg + + [tool:pytest] + asyncio_default_fixture_loop_scope = session + +Please refer to :ref:`configuration/asyncio_default_fixture_loop_scope` for other valid scopes. diff --git a/docs/source/how-to-guides/index.rst b/docs/source/how-to-guides/index.rst index e47561d2..4f03dd35 100644 --- a/docs/source/how-to-guides/index.rst +++ b/docs/source/how-to-guides/index.rst @@ -6,6 +6,7 @@ How-To Guides :hidden: change_fixture_loop + change_default_fixture_loop run_class_tests_in_same_loop run_module_tests_in_same_loop run_package_tests_in_same_loop diff --git a/docs/source/reference/configuration.rst b/docs/source/reference/configuration.rst index 7b0d1f95..35c67302 100644 --- a/docs/source/reference/configuration.rst +++ b/docs/source/reference/configuration.rst @@ -2,6 +2,8 @@ Configuration ============= +.. _configuration/asyncio_default_fixture_loop_scope: + asyncio_default_fixture_loop_scope ================================== Determines the default event loop scope of asynchronous fixtures. When this configuration option is unset, it defaults to the fixture scope. In future versions of pytest-asyncio, the value will default to ``function`` when unset. Possible values are: ``function``, ``class``, ``module``, ``package``, ``session`` From 57c297480dc1081937738e813174ab3a82673a9d Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Thu, 25 Jul 2024 09:23:48 +0200 Subject: [PATCH 022/226] 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(): ... From 13e8f25abdac167b60e22524c01fe4bf40bff166 Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Thu, 25 Jul 2024 09:45:56 +0200 Subject: [PATCH 023/226] docs: Added missing changelog entry about the loop_scope kwarg. Signed-off-by: Michael Seifert --- docs/source/reference/changelog.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/source/reference/changelog.rst b/docs/source/reference/changelog.rst index 9c58ae44..82987a05 100644 --- a/docs/source/reference/changelog.rst +++ b/docs/source/reference/changelog.rst @@ -4,7 +4,8 @@ Changelog 0.24.0 (UNRELEASED) =================== -- Deprecates the optional `scope` keyword argument of asyncio markers. Users are encouraged to use the `loop_scope` keyword argument. The `loop_scope` kwarg does exactly the same, though its naming is consistent with the `loop_scope` kwarg of ``pytest_asyncio.fixture``. +- Adds an optional `loop_scope` keyword argument to `pytest.mark.asyncio`. This argument controls which event loop is used to run the marked async test. `#706`_, `#871 `_ +- Deprecates the optional `scope` keyword argument to `pytest.mark.asyncio` for API consistency with ``pytest_asyncio.fixture``. Users are encouraged to use the `loop_scope` keyword argument, which does exactly the same. 0.23.8 (2024-07-17) From b77241f8274f2e9410b249bb9f8df11915202bee Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Jul 2024 18:47:05 +0000 Subject: [PATCH 024/226] Build(deps): Bump sphinxcontrib-htmlhelp in /dependencies/docs Bumps [sphinxcontrib-htmlhelp](https://github.com/sphinx-doc/sphinxcontrib-htmlhelp) from 2.0.6 to 2.1.0. - [Release notes](https://github.com/sphinx-doc/sphinxcontrib-htmlhelp/releases) - [Changelog](https://github.com/sphinx-doc/sphinxcontrib-htmlhelp/blob/master/CHANGES.rst) - [Commits](https://github.com/sphinx-doc/sphinxcontrib-htmlhelp/compare/2.0.6...2.1.0) --- updated-dependencies: - dependency-name: sphinxcontrib-htmlhelp dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- dependencies/docs/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/docs/constraints.txt b/dependencies/docs/constraints.txt index 9906c5fa..14a905d0 100644 --- a/dependencies/docs/constraints.txt +++ b/dependencies/docs/constraints.txt @@ -15,7 +15,7 @@ Sphinx==7.4.7 sphinx-rtd-theme==2.0.0 sphinxcontrib-applehelp==1.0.8 sphinxcontrib-devhelp==1.0.6 -sphinxcontrib-htmlhelp==2.0.6 +sphinxcontrib-htmlhelp==2.1.0 sphinxcontrib-jquery==4.1 sphinxcontrib-jsmath==1.0.1 sphinxcontrib-qthelp==1.0.8 From a8b3d18be6e7ebe752c5e06d7f820a5527f48e93 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Jul 2024 18:47:02 +0000 Subject: [PATCH 025/226] Build(deps): Bump sphinxcontrib-qthelp in /dependencies/docs Bumps [sphinxcontrib-qthelp](https://github.com/sphinx-doc/sphinxcontrib-qthelp) from 1.0.8 to 2.0.0. - [Release notes](https://github.com/sphinx-doc/sphinxcontrib-qthelp/releases) - [Changelog](https://github.com/sphinx-doc/sphinxcontrib-qthelp/blob/master/CHANGES.rst) - [Commits](https://github.com/sphinx-doc/sphinxcontrib-qthelp/compare/1.0.8...2.0.0) --- updated-dependencies: - dependency-name: sphinxcontrib-qthelp dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- dependencies/docs/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/docs/constraints.txt b/dependencies/docs/constraints.txt index 14a905d0..38a1884e 100644 --- a/dependencies/docs/constraints.txt +++ b/dependencies/docs/constraints.txt @@ -18,6 +18,6 @@ sphinxcontrib-devhelp==1.0.6 sphinxcontrib-htmlhelp==2.1.0 sphinxcontrib-jquery==4.1 sphinxcontrib-jsmath==1.0.1 -sphinxcontrib-qthelp==1.0.8 +sphinxcontrib-qthelp==2.0.0 sphinxcontrib-serializinghtml==1.1.10 urllib3==2.2.2 From 102a1afdee56e19e1480a76760349e16b99f6ca0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Jul 2024 18:46:56 +0000 Subject: [PATCH 026/226] Build(deps): Bump sphinxcontrib-serializinghtml in /dependencies/docs Bumps [sphinxcontrib-serializinghtml](https://github.com/sphinx-doc/sphinxcontrib-serializinghtml) from 1.1.10 to 2.0.0. - [Release notes](https://github.com/sphinx-doc/sphinxcontrib-serializinghtml/releases) - [Changelog](https://github.com/sphinx-doc/sphinxcontrib-serializinghtml/blob/master/CHANGES.rst) - [Commits](https://github.com/sphinx-doc/sphinxcontrib-serializinghtml/compare/1.1.10...2.0.0) --- updated-dependencies: - dependency-name: sphinxcontrib-serializinghtml dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- dependencies/docs/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/docs/constraints.txt b/dependencies/docs/constraints.txt index 38a1884e..e10e29f5 100644 --- a/dependencies/docs/constraints.txt +++ b/dependencies/docs/constraints.txt @@ -19,5 +19,5 @@ sphinxcontrib-htmlhelp==2.1.0 sphinxcontrib-jquery==4.1 sphinxcontrib-jsmath==1.0.1 sphinxcontrib-qthelp==2.0.0 -sphinxcontrib-serializinghtml==1.1.10 +sphinxcontrib-serializinghtml==2.0.0 urllib3==2.2.2 From fddef6f39866b4086bc1b7d9184c3a2c1a36aea5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Jul 2024 18:46:58 +0000 Subject: [PATCH 027/226] Build(deps): Bump sphinxcontrib-applehelp in /dependencies/docs Bumps [sphinxcontrib-applehelp](https://github.com/sphinx-doc/sphinxcontrib-applehelp) from 1.0.8 to 2.0.0. - [Release notes](https://github.com/sphinx-doc/sphinxcontrib-applehelp/releases) - [Changelog](https://github.com/sphinx-doc/sphinxcontrib-applehelp/blob/master/CHANGES.rst) - [Commits](https://github.com/sphinx-doc/sphinxcontrib-applehelp/compare/1.0.8...2.0.0) --- updated-dependencies: - dependency-name: sphinxcontrib-applehelp dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- dependencies/docs/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/docs/constraints.txt b/dependencies/docs/constraints.txt index e10e29f5..5fb80440 100644 --- a/dependencies/docs/constraints.txt +++ b/dependencies/docs/constraints.txt @@ -13,7 +13,7 @@ requests==2.32.3 snowballstemmer==2.2.0 Sphinx==7.4.7 sphinx-rtd-theme==2.0.0 -sphinxcontrib-applehelp==1.0.8 +sphinxcontrib-applehelp==2.0.0 sphinxcontrib-devhelp==1.0.6 sphinxcontrib-htmlhelp==2.1.0 sphinxcontrib-jquery==4.1 From a07d5b949e7369a6acd0be1f12711e5caeb2a644 Mon Sep 17 00:00:00 2001 From: Christoph Zwerschke Date: Thu, 18 Jul 2024 22:18:04 +0200 Subject: [PATCH 028/226] feat: Check marker arguments docs: Added changelog entry for error for positional asyncio marker arguments. --- docs/source/reference/changelog.rst | 1 + pytest_asyncio/plugin.py | 4 ++ tests/markers/test_invalid_arguments.py | 85 +++++++++++++++++++++++++ 3 files changed, 90 insertions(+) create mode 100644 tests/markers/test_invalid_arguments.py diff --git a/docs/source/reference/changelog.rst b/docs/source/reference/changelog.rst index 82987a05..c976b8da 100644 --- a/docs/source/reference/changelog.rst +++ b/docs/source/reference/changelog.rst @@ -6,6 +6,7 @@ Changelog =================== - Adds an optional `loop_scope` keyword argument to `pytest.mark.asyncio`. This argument controls which event loop is used to run the marked async test. `#706`_, `#871 `_ - Deprecates the optional `scope` keyword argument to `pytest.mark.asyncio` for API consistency with ``pytest_asyncio.fixture``. Users are encouraged to use the `loop_scope` keyword argument, which does exactly the same. +- Raises an error when passing `scope` or `loop_scope` as a positional argument to ``@pytest.mark.asyncio``. `#812 `_ 0.23.8 (2024-07-17) diff --git a/pytest_asyncio/plugin.py b/pytest_asyncio/plugin.py index aaa1e8f3..a90e125e 100644 --- a/pytest_asyncio/plugin.py +++ b/pytest_asyncio/plugin.py @@ -1004,6 +1004,10 @@ def pytest_runtest_setup(item: pytest.Item) -> None: def _get_marked_loop_scope(asyncio_marker: Mark) -> _ScopeName: assert asyncio_marker.name == "asyncio" + if asyncio_marker.args or ( + asyncio_marker.kwargs and set(asyncio_marker.kwargs) - {"loop_scope", "scope"} + ): + raise ValueError("mark.asyncio accepts only a keyword argument 'scope'.") if "scope" in asyncio_marker.kwargs: if "loop_scope" in asyncio_marker.kwargs: raise pytest.UsageError(_DUPLICATE_LOOP_SCOPE_DEFINITION_ERROR) diff --git a/tests/markers/test_invalid_arguments.py b/tests/markers/test_invalid_arguments.py new file mode 100644 index 00000000..a4f4b070 --- /dev/null +++ b/tests/markers/test_invalid_arguments.py @@ -0,0 +1,85 @@ +from textwrap import dedent + +import pytest + + +def test_no_error_when_scope_passed_as_sole_keyword_argument( + pytester: pytest.Pytester, +): + pytester.makepyfile( + dedent( + """\ + import pytest + + @pytest.mark.asyncio(loop_scope="session") + async def test_anything(): + pass + """ + ) + ) + result = pytester.runpytest_subprocess() + result.assert_outcomes(passed=1) + result.stdout.no_fnmatch_line("*ValueError*") + + +def test_error_when_scope_passed_as_positional_argument( + pytester: pytest.Pytester, +): + pytester.makepyfile( + dedent( + """\ + import pytest + + @pytest.mark.asyncio("session") + async def test_anything(): + pass + """ + ) + ) + result = pytester.runpytest_subprocess() + result.assert_outcomes(errors=1) + result.stdout.fnmatch_lines( + ["*ValueError: mark.asyncio accepts only a keyword argument*"] + ) + + +def test_error_when_wrong_keyword_argument_is_passed( + pytester: pytest.Pytester, +): + pytester.makepyfile( + dedent( + """\ + import pytest + + @pytest.mark.asyncio(cope="session") + async def test_anything(): + pass + """ + ) + ) + result = pytester.runpytest_subprocess() + result.assert_outcomes(errors=1) + result.stdout.fnmatch_lines( + ["*ValueError: mark.asyncio accepts only a keyword argument 'scope'*"] + ) + + +def test_error_when_additional_keyword_arguments_are_passed( + pytester: pytest.Pytester, +): + pytester.makepyfile( + dedent( + """\ + import pytest + + @pytest.mark.asyncio(loop_scope="session", more="stuff") + async def test_anything(): + pass + """ + ) + ) + result = pytester.runpytest_subprocess() + result.assert_outcomes(errors=1) + result.stdout.fnmatch_lines( + ["*ValueError: mark.asyncio accepts only a keyword argument*"] + ) From cbb39a0838790facb4c584c1a13aa4a785075d67 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Jul 2024 18:46:54 +0000 Subject: [PATCH 029/226] Build(deps): Bump sphinxcontrib-devhelp in /dependencies/docs Bumps [sphinxcontrib-devhelp](https://github.com/sphinx-doc/sphinxcontrib-devhelp) from 1.0.6 to 2.0.0. - [Release notes](https://github.com/sphinx-doc/sphinxcontrib-devhelp/releases) - [Changelog](https://github.com/sphinx-doc/sphinxcontrib-devhelp/blob/master/CHANGES.rst) - [Commits](https://github.com/sphinx-doc/sphinxcontrib-devhelp/compare/1.0.6...2.0.0) --- updated-dependencies: - dependency-name: sphinxcontrib-devhelp dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- dependencies/docs/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/docs/constraints.txt b/dependencies/docs/constraints.txt index 5fb80440..dffb4bf5 100644 --- a/dependencies/docs/constraints.txt +++ b/dependencies/docs/constraints.txt @@ -14,7 +14,7 @@ snowballstemmer==2.2.0 Sphinx==7.4.7 sphinx-rtd-theme==2.0.0 sphinxcontrib-applehelp==2.0.0 -sphinxcontrib-devhelp==1.0.6 +sphinxcontrib-devhelp==2.0.0 sphinxcontrib-htmlhelp==2.1.0 sphinxcontrib-jquery==4.1 sphinxcontrib-jsmath==1.0.1 From 739552c419304eda29ec889c04d59f3a12847850 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 5 Aug 2024 23:10:21 +0000 Subject: [PATCH 030/226] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/mirrors-mypy: v1.11.0 → v1.11.1](https://github.com/pre-commit/mirrors-mypy/compare/v1.11.0...v1.11.1) - [github.com/pycqa/flake8: 7.1.0 → 7.1.1](https://github.com/pycqa/flake8/compare/7.1.0...7.1.1) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5c49fd36..f7b2a7f5 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -37,14 +37,14 @@ repos: - id: check-yaml - id: debug-statements - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.11.0 + rev: v1.11.1 hooks: - id: mypy exclude: ^(docs|tests)/.* additional_dependencies: - pytest - repo: https://github.com/pycqa/flake8 - rev: 7.1.0 + rev: 7.1.1 hooks: - id: flake8 language_version: python3 From 597eba7feafd0ea1baa3dae5aa2f4854db68480d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Aug 2024 18:49:44 +0000 Subject: [PATCH 031/226] Build(deps): Bump coverage from 7.6.0 to 7.6.1 in /dependencies/default Bumps [coverage](https://github.com/nedbat/coveragepy) from 7.6.0 to 7.6.1. - [Release notes](https://github.com/nedbat/coveragepy/releases) - [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst) - [Commits](https://github.com/nedbat/coveragepy/compare/7.6.0...7.6.1) --- updated-dependencies: - dependency-name: coverage dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index 2ea3a028..d05a7d3e 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -1,5 +1,5 @@ attrs==23.2.0 -coverage==7.6.0 +coverage==7.6.1 exceptiongroup==1.2.2 hypothesis==6.108.5 iniconfig==2.0.0 From 991b9dee76c4ea95d83f19d9a1a68f6e71c9a5ef Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 6 Aug 2024 07:02:15 +0000 Subject: [PATCH 032/226] Build(deps): Bump attrs from 23.2.0 to 24.1.0 in /dependencies/default Bumps [attrs](https://github.com/sponsors/hynek) from 23.2.0 to 24.1.0. - [Commits](https://github.com/sponsors/hynek/commits) --- updated-dependencies: - dependency-name: attrs dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index d05a7d3e..dabdf00c 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -1,4 +1,4 @@ -attrs==23.2.0 +attrs==24.1.0 coverage==7.6.1 exceptiongroup==1.2.2 hypothesis==6.108.5 From 852b080eee9898d06f303ae695792b2943e96ea9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 6 Aug 2024 07:02:34 +0000 Subject: [PATCH 033/226] Build(deps): Bump hypothesis in /dependencies/default Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.108.5 to 6.108.9. - [Release notes](https://github.com/HypothesisWorks/hypothesis/releases) - [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.108.5...hypothesis-python-6.108.9) --- updated-dependencies: - dependency-name: hypothesis dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index dabdf00c..98720d47 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -1,7 +1,7 @@ attrs==24.1.0 coverage==7.6.1 exceptiongroup==1.2.2 -hypothesis==6.108.5 +hypothesis==6.108.9 iniconfig==2.0.0 packaging==24.1 pluggy==1.5.0 From 825c8a1709472414ecedb3f9e36e6e613275f1d0 Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Mon, 15 Jul 2024 17:02:09 +0200 Subject: [PATCH 034/226] ci: No longer install tox during the build job. It isn't used during the build job. Signed-off-by: Michael Seifert --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 620a65cc..a6851845 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -35,7 +35,7 @@ jobs: - name: Run pre-commit checks run: pre-commit run --all-files --show-diff-on-failure - name: Install check-wheel-content, and twine - run: python -m pip install build check-wheel-contents tox twine + run: python -m pip install build check-wheel-contents twine - name: Build package run: python -m build - name: List result From eb0b3d2b5838cbc9b9ee3cc8fa4aa3e65840bed9 Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Wed, 7 Aug 2024 06:46:24 +0200 Subject: [PATCH 035/226] Revert "build: Remove development dependency on Docker." This reverts commit b735e8a8ef3118109521c7b058596cf7decb03d0. --- .pre-commit-config.yaml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f7b2a7f5..ef53ca94 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -52,10 +52,22 @@ repos: rev: v1.10.0 hooks: - id: python-use-type-annotations +- repo: https://github.com/rhysd/actionlint + rev: v1.6.22 + hooks: + - id: actionlint-docker + args: + - -ignore + - 'SC2155:' + - -ignore + - 'SC2086:' + - -ignore + - 'SC1004:' - repo: https://github.com/sirosen/check-jsonschema rev: 0.29.1 hooks: - id: check-github-actions ci: skip: + - actionlint-docker - check-github-actions From f45aa18cf3eeeb94075de16a1d797858facab863 Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Wed, 7 Aug 2024 07:07:04 +0200 Subject: [PATCH 036/226] build: Run actionlint pre-commit hook in manual stage. Compared to running the hook in the default stage, this doesn't require a working Docker installation to make changes. --- .pre-commit-config.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ef53ca94..6ac3ce3e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -63,6 +63,7 @@ repos: - 'SC2086:' - -ignore - 'SC1004:' + stages: [manual] - repo: https://github.com/sirosen/check-jsonschema rev: 0.29.1 hooks: From 6f33fedd9d398267398d8189c1c08d2b812d8a9d Mon Sep 17 00:00:00 2001 From: Albin Skott Date: Mon, 5 Aug 2024 15:07:38 +0200 Subject: [PATCH 037/226] fix: Fixes a bug that caused module-scoped async fixtures to fail when reused in other modules. Async fixture synchronizers now choose the event loop for the async fixutre at runtime rather than relying on collection-time information. This fixes #862. --- pytest_asyncio/plugin.py | 92 +++++++++---------- .../test_shared_module_fixture.py | 35 +++++++ 2 files changed, 78 insertions(+), 49 deletions(-) create mode 100644 tests/async_fixtures/test_shared_module_fixture.py diff --git a/pytest_asyncio/plugin.py b/pytest_asyncio/plugin.py index a90e125e..39d1a08d 100644 --- a/pytest_asyncio/plugin.py +++ b/pytest_asyncio/plugin.py @@ -251,15 +251,8 @@ def _preprocess_async_fixtures( or default_loop_scope or fixturedef.scope ) - if scope == "function": - event_loop_fixture_id: Optional[str] = "event_loop" - else: - event_loop_node = _retrieve_scope_root(collector, scope) - event_loop_fixture_id = event_loop_node.stash.get( - # Type ignored because of non-optimal mypy inference. - _event_loop_fixture_id, # type: ignore[arg-type] - None, - ) + if scope == "function" and "event_loop" not in fixturedef.argnames: + fixturedef.argnames += ("event_loop",) _make_asyncio_fixture_function(func, scope) function_signature = inspect.signature(func) if "event_loop" in function_signature.parameters: @@ -271,49 +264,26 @@ def _preprocess_async_fixtures( f"instead." ) ) - assert event_loop_fixture_id - _inject_fixture_argnames( - fixturedef, - event_loop_fixture_id, - ) - _synchronize_async_fixture( - fixturedef, - event_loop_fixture_id, - ) + if "request" not in fixturedef.argnames: + fixturedef.argnames += ("request",) + _synchronize_async_fixture(fixturedef) assert _is_asyncio_fixture_function(fixturedef.func) processed_fixturedefs.add(fixturedef) -def _inject_fixture_argnames( - fixturedef: FixtureDef, event_loop_fixture_id: str -) -> None: - """ - Ensures that `request` and `event_loop` are arguments of the specified fixture. - """ - to_add = [] - for name in ("request", event_loop_fixture_id): - if name not in fixturedef.argnames: - to_add.append(name) - if to_add: - fixturedef.argnames += tuple(to_add) - - -def _synchronize_async_fixture( - fixturedef: FixtureDef, event_loop_fixture_id: str -) -> None: +def _synchronize_async_fixture(fixturedef: FixtureDef) -> None: """ Wraps the fixture function of an async fixture in a synchronous function. """ if inspect.isasyncgenfunction(fixturedef.func): - _wrap_asyncgen_fixture(fixturedef, event_loop_fixture_id) + _wrap_asyncgen_fixture(fixturedef) elif inspect.iscoroutinefunction(fixturedef.func): - _wrap_async_fixture(fixturedef, event_loop_fixture_id) + _wrap_async_fixture(fixturedef) def _add_kwargs( func: Callable[..., Any], kwargs: Dict[str, Any], - event_loop_fixture_id: str, event_loop: asyncio.AbstractEventLoop, request: FixtureRequest, ) -> Dict[str, Any]: @@ -321,8 +291,8 @@ def _add_kwargs( ret = kwargs.copy() if "request" in sig.parameters: ret["request"] = request - if event_loop_fixture_id in sig.parameters: - ret[event_loop_fixture_id] = event_loop + if "event_loop" in sig.parameters: + ret["event_loop"] = event_loop return ret @@ -345,17 +315,19 @@ def _perhaps_rebind_fixture_func( return func -def _wrap_asyncgen_fixture(fixturedef: FixtureDef, event_loop_fixture_id: str) -> None: +def _wrap_asyncgen_fixture(fixturedef: FixtureDef) -> None: fixture = fixturedef.func @functools.wraps(fixture) def _asyncgen_fixture_wrapper(request: FixtureRequest, **kwargs: Any): unittest = fixturedef.unittest if hasattr(fixturedef, "unittest") else False func = _perhaps_rebind_fixture_func(fixture, request.instance, unittest) - event_loop = kwargs.pop(event_loop_fixture_id) - gen_obj = func( - **_add_kwargs(func, kwargs, event_loop_fixture_id, event_loop, request) + event_loop_fixture_id = _get_event_loop_fixture_id_for_async_fixture( + request, func ) + event_loop = request.getfixturevalue(event_loop_fixture_id) + kwargs.pop(event_loop_fixture_id, None) + gen_obj = func(**_add_kwargs(func, kwargs, event_loop, request)) async def setup(): res = await gen_obj.__anext__() @@ -383,19 +355,21 @@ async def async_finalizer() -> None: fixturedef.func = _asyncgen_fixture_wrapper -def _wrap_async_fixture(fixturedef: FixtureDef, event_loop_fixture_id: str) -> None: +def _wrap_async_fixture(fixturedef: FixtureDef) -> None: fixture = fixturedef.func @functools.wraps(fixture) def _async_fixture_wrapper(request: FixtureRequest, **kwargs: Any): unittest = False if pytest.version_tuple >= (8, 2) else fixturedef.unittest func = _perhaps_rebind_fixture_func(fixture, request.instance, unittest) - event_loop = kwargs.pop(event_loop_fixture_id) + event_loop_fixture_id = _get_event_loop_fixture_id_for_async_fixture( + request, func + ) + event_loop = request.getfixturevalue(event_loop_fixture_id) + kwargs.pop(event_loop_fixture_id, None) async def setup(): - res = await func( - **_add_kwargs(func, kwargs, event_loop_fixture_id, event_loop, request) - ) + res = await func(**_add_kwargs(func, kwargs, event_loop, request)) return res return event_loop.run_until_complete(setup()) @@ -403,6 +377,26 @@ async def setup(): fixturedef.func = _async_fixture_wrapper +def _get_event_loop_fixture_id_for_async_fixture( + request: FixtureRequest, func: Any +) -> str: + default_loop_scope = request.config.getini("asyncio_default_fixture_loop_scope") + loop_scope = ( + getattr(func, "_loop_scope", None) or default_loop_scope or request.scope + ) + if loop_scope == "function": + event_loop_fixture_id = "event_loop" + else: + event_loop_node = _retrieve_scope_root(request._pyfuncitem, loop_scope) + event_loop_fixture_id = event_loop_node.stash.get( + # Type ignored because of non-optimal mypy inference. + _event_loop_fixture_id, # type: ignore[arg-type] + "", + ) + assert event_loop_fixture_id + return event_loop_fixture_id + + class PytestAsyncioFunction(Function): """Base class for all test functions managed by pytest-asyncio.""" diff --git a/tests/async_fixtures/test_shared_module_fixture.py b/tests/async_fixtures/test_shared_module_fixture.py new file mode 100644 index 00000000..ff1cb62b --- /dev/null +++ b/tests/async_fixtures/test_shared_module_fixture.py @@ -0,0 +1,35 @@ +from textwrap import dedent + +from pytest import Pytester + + +def test_asyncio_mark_provides_package_scoped_loop_strict_mode(pytester: Pytester): + pytester.makepyfile( + __init__="", + conftest=dedent( + """\ + import pytest_asyncio + @pytest_asyncio.fixture(scope="module") + async def async_shared_module_fixture(): + return True + """ + ), + test_module_one=dedent( + """\ + import pytest + @pytest.mark.asyncio + async def test_shared_module_fixture_use_a(async_shared_module_fixture): + assert async_shared_module_fixture is True + """ + ), + test_module_two=dedent( + """\ + import pytest + @pytest.mark.asyncio + async def test_shared_module_fixture_use_b(async_shared_module_fixture): + assert async_shared_module_fixture is True + """ + ), + ) + result = pytester.runpytest("--asyncio-mode=strict") + result.assert_outcomes(passed=2) From 0c50db59afd0f509179ad01251766f75551589ae Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Wed, 7 Aug 2024 12:13:19 +0200 Subject: [PATCH 038/226] docs: Added changelog entry. --- docs/source/reference/changelog.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/source/reference/changelog.rst b/docs/source/reference/changelog.rst index c976b8da..f4067f20 100644 --- a/docs/source/reference/changelog.rst +++ b/docs/source/reference/changelog.rst @@ -7,6 +7,7 @@ Changelog - Adds an optional `loop_scope` keyword argument to `pytest.mark.asyncio`. This argument controls which event loop is used to run the marked async test. `#706`_, `#871 `_ - Deprecates the optional `scope` keyword argument to `pytest.mark.asyncio` for API consistency with ``pytest_asyncio.fixture``. Users are encouraged to use the `loop_scope` keyword argument, which does exactly the same. - Raises an error when passing `scope` or `loop_scope` as a positional argument to ``@pytest.mark.asyncio``. `#812 `_ +- Fixes a bug that caused module-scoped async fixtures to fail when reused in other modules `#862 `_ `#668 `_ 0.23.8 (2024-07-17) From 4609c74123b489ab5516f02d3338ed96e12b1174 Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Wed, 7 Aug 2024 13:00:01 +0200 Subject: [PATCH 039/226] build: Bump minimum supported pytest version to v8.2.0. --- dependencies/default/requirements.txt | 2 +- dependencies/pytest-min/constraints.txt | 4 ++-- dependencies/pytest-min/requirements.txt | 2 +- docs/source/reference/changelog.rst | 1 + setup.cfg | 2 +- tests/test_is_async_test.py | 5 +---- 6 files changed, 7 insertions(+), 9 deletions(-) diff --git a/dependencies/default/requirements.txt b/dependencies/default/requirements.txt index 3ac25aba..42cfc8d3 100644 --- a/dependencies/default/requirements.txt +++ b/dependencies/default/requirements.txt @@ -1,3 +1,3 @@ # Always adjust install_requires in setup.cfg and pytest-min-requirements.txt # when changing runtime dependencies -pytest >= 7.0.0,<9 +pytest >= 8.2,<9 diff --git a/dependencies/pytest-min/constraints.txt b/dependencies/pytest-min/constraints.txt index 65e3addb..f01a0eb7 100644 --- a/dependencies/pytest-min/constraints.txt +++ b/dependencies/pytest-min/constraints.txt @@ -11,10 +11,10 @@ iniconfig==2.0.0 mock==5.1.0 nose==1.3.7 packaging==23.2 -pluggy==1.3.0 +pluggy==1.5.0 py==1.11.0 Pygments==2.16.1 -pytest==7.0.0 +pytest==8.2.0 requests==2.31.0 sortedcontainers==2.4.0 tomli==2.0.1 diff --git a/dependencies/pytest-min/requirements.txt b/dependencies/pytest-min/requirements.txt index 9fb33e96..918abfd5 100644 --- a/dependencies/pytest-min/requirements.txt +++ b/dependencies/pytest-min/requirements.txt @@ -1,3 +1,3 @@ # Always adjust install_requires in setup.cfg and requirements.txt # when changing minimum version dependencies -pytest[testing] == 7.0.0 +pytest[testing] == 8.2.0 diff --git a/docs/source/reference/changelog.rst b/docs/source/reference/changelog.rst index f4067f20..abf27a0a 100644 --- a/docs/source/reference/changelog.rst +++ b/docs/source/reference/changelog.rst @@ -4,6 +4,7 @@ Changelog 0.24.0 (UNRELEASED) =================== +- BREAKING: Updated minimum supported pytest version to v8.2.0 - Adds an optional `loop_scope` keyword argument to `pytest.mark.asyncio`. This argument controls which event loop is used to run the marked async test. `#706`_, `#871 `_ - Deprecates the optional `scope` keyword argument to `pytest.mark.asyncio` for API consistency with ``pytest_asyncio.fixture``. Users are encouraged to use the `loop_scope` keyword argument, which does exactly the same. - Raises an error when passing `scope` or `loop_scope` as a positional argument to ``@pytest.mark.asyncio``. `#812 `_ diff --git a/setup.cfg b/setup.cfg index 9947cbe3..c04d3884 100644 --- a/setup.cfg +++ b/setup.cfg @@ -41,7 +41,7 @@ include_package_data = True # Always adjust requirements.txt and pytest-min-requirements.txt when changing runtime dependencies install_requires = - pytest >= 7.0.0,<9 + pytest >= 8.2,<9 [options.extras_require] testing = diff --git a/tests/test_is_async_test.py b/tests/test_is_async_test.py index 12e791c1..cf98cc94 100644 --- a/tests/test_is_async_test.py +++ b/tests/test_is_async_test.py @@ -74,10 +74,7 @@ def pytest_collection_modifyitems(items): ) ) result = pytester.runpytest("--asyncio-mode=strict") - if pytest.version_tuple < (7, 2): - # Probably related to https://github.com/pytest-dev/pytest/pull/10012 - result.assert_outcomes(failed=1) - elif pytest.version_tuple < (8,): + if pytest.version_tuple < (8,): result.assert_outcomes(skipped=1) else: result.assert_outcomes(failed=1) From 6bc3c44c042cdd1bdd77a72948ee07538e6033fe Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Wed, 7 Aug 2024 14:11:41 +0200 Subject: [PATCH 040/226] refactor: Removed version-specific code paths for pytest versions lower than 8.2 --- pytest_asyncio/plugin.py | 21 +++++++-------------- tests/test_is_async_test.py | 6 +----- 2 files changed, 8 insertions(+), 19 deletions(-) diff --git a/pytest_asyncio/plugin.py b/pytest_asyncio/plugin.py index 39d1a08d..85235de4 100644 --- a/pytest_asyncio/plugin.py +++ b/pytest_asyncio/plugin.py @@ -35,6 +35,7 @@ Class, Collector, Config, + FixtureDef, FixtureRequest, Function, Item, @@ -62,12 +63,6 @@ FixtureFunction = Union[SimpleFixtureFunction, FactoryFixtureFunction] FixtureFunctionMarker = Callable[[FixtureFunction], FixtureFunction] -# https://github.com/pytest-dev/pytest/commit/fb55615d5e999dd44306596f340036c195428ef1 -if pytest.version_tuple < (8, 0): - FixtureDef = Any -else: - from pytest import FixtureDef - class PytestAsyncioError(Exception): """Base class for exceptions raised by pytest-asyncio""" @@ -320,8 +315,7 @@ def _wrap_asyncgen_fixture(fixturedef: FixtureDef) -> None: @functools.wraps(fixture) def _asyncgen_fixture_wrapper(request: FixtureRequest, **kwargs: Any): - unittest = fixturedef.unittest if hasattr(fixturedef, "unittest") else False - func = _perhaps_rebind_fixture_func(fixture, request.instance, unittest) + func = _perhaps_rebind_fixture_func(fixture, request.instance, False) event_loop_fixture_id = _get_event_loop_fixture_id_for_async_fixture( request, func ) @@ -330,7 +324,7 @@ def _asyncgen_fixture_wrapper(request: FixtureRequest, **kwargs: Any): gen_obj = func(**_add_kwargs(func, kwargs, event_loop, request)) async def setup(): - res = await gen_obj.__anext__() + res = await gen_obj.__anext__() # type: ignore[union-attr] return res def finalizer() -> None: @@ -338,7 +332,7 @@ def finalizer() -> None: async def async_finalizer() -> None: try: - await gen_obj.__anext__() + await gen_obj.__anext__() # type: ignore[union-attr] except StopAsyncIteration: pass else: @@ -352,7 +346,7 @@ async def async_finalizer() -> None: request.addfinalizer(finalizer) return result - fixturedef.func = _asyncgen_fixture_wrapper + fixturedef.func = _asyncgen_fixture_wrapper # type: ignore[misc] def _wrap_async_fixture(fixturedef: FixtureDef) -> None: @@ -360,8 +354,7 @@ def _wrap_async_fixture(fixturedef: FixtureDef) -> None: @functools.wraps(fixture) def _async_fixture_wrapper(request: FixtureRequest, **kwargs: Any): - unittest = False if pytest.version_tuple >= (8, 2) else fixturedef.unittest - func = _perhaps_rebind_fixture_func(fixture, request.instance, unittest) + func = _perhaps_rebind_fixture_func(fixture, request.instance, False) event_loop_fixture_id = _get_event_loop_fixture_id_for_async_fixture( request, func ) @@ -374,7 +367,7 @@ async def setup(): return event_loop.run_until_complete(setup()) - fixturedef.func = _async_fixture_wrapper + fixturedef.func = _async_fixture_wrapper # type: ignore[misc] def _get_event_loop_fixture_id_for_async_fixture( diff --git a/tests/test_is_async_test.py b/tests/test_is_async_test.py index cf98cc94..e0df54de 100644 --- a/tests/test_is_async_test.py +++ b/tests/test_is_async_test.py @@ -1,6 +1,5 @@ from textwrap import dedent -import pytest from pytest import Pytester @@ -74,10 +73,7 @@ def pytest_collection_modifyitems(items): ) ) result = pytester.runpytest("--asyncio-mode=strict") - if pytest.version_tuple < (8,): - result.assert_outcomes(skipped=1) - else: - result.assert_outcomes(failed=1) + result.assert_outcomes(failed=1) def test_returns_true_for_unmarked_coroutine_item_in_auto_mode(pytester: Pytester): From 923399dff75c4d3f318b9700248639f815fa2f38 Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Wed, 7 Aug 2024 14:20:58 +0200 Subject: [PATCH 041/226] refactor: Removed obsolete "unittest" argument from _perhabs_rebind_fixture_func --- pytest_asyncio/plugin.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/pytest_asyncio/plugin.py b/pytest_asyncio/plugin.py index 85235de4..af403053 100644 --- a/pytest_asyncio/plugin.py +++ b/pytest_asyncio/plugin.py @@ -291,9 +291,7 @@ def _add_kwargs( return ret -def _perhaps_rebind_fixture_func( - func: _T, instance: Optional[Any], unittest: bool -) -> _T: +def _perhaps_rebind_fixture_func(func: _T, instance: Optional[Any]) -> _T: if instance is not None: # The fixture needs to be bound to the actual request.instance # so it is bound to the same object as the test method. @@ -302,10 +300,9 @@ def _perhaps_rebind_fixture_func( unbound, cls = func.__func__, type(func.__self__) # type: ignore except AttributeError: pass - # If unittest is true, the fixture is bound unconditionally. - # otherwise, only if the fixture was bound before to an instance of + # Only if the fixture was bound before to an instance of # the same type. - if unittest or (cls is not None and isinstance(instance, cls)): + if cls is not None and isinstance(instance, cls): func = unbound.__get__(instance) # type: ignore return func @@ -315,7 +312,7 @@ def _wrap_asyncgen_fixture(fixturedef: FixtureDef) -> None: @functools.wraps(fixture) def _asyncgen_fixture_wrapper(request: FixtureRequest, **kwargs: Any): - func = _perhaps_rebind_fixture_func(fixture, request.instance, False) + func = _perhaps_rebind_fixture_func(fixture, request.instance) event_loop_fixture_id = _get_event_loop_fixture_id_for_async_fixture( request, func ) @@ -354,7 +351,7 @@ def _wrap_async_fixture(fixturedef: FixtureDef) -> None: @functools.wraps(fixture) def _async_fixture_wrapper(request: FixtureRequest, **kwargs: Any): - func = _perhaps_rebind_fixture_func(fixture, request.instance, False) + func = _perhaps_rebind_fixture_func(fixture, request.instance) event_loop_fixture_id = _get_event_loop_fixture_id_for_async_fixture( request, func ) From d0318c3d4924df913bc42d9e1f32f47c1873aae4 Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Wed, 7 Aug 2024 14:38:31 +0200 Subject: [PATCH 042/226] refactor: Narrowed down return type of pytest_pycollect_makeitem_convert_async_functions_to_subclass. --- pytest_asyncio/plugin.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pytest_asyncio/plugin.py b/pytest_asyncio/plugin.py index af403053..a653ace5 100644 --- a/pytest_asyncio/plugin.py +++ b/pytest_asyncio/plugin.py @@ -30,6 +30,7 @@ overload, ) +import pluggy import pytest from pytest import ( Class, @@ -539,13 +540,12 @@ def pytest_pycollect_makeitem_preprocess_async_fixtures( return None -# TODO: #778 Narrow down return type of function when dropping support for pytest 7 # The function name needs to start with "pytest_" # see https://github.com/pytest-dev/pytest/issues/11307 @pytest.hookimpl(specname="pytest_pycollect_makeitem", hookwrapper=True) def pytest_pycollect_makeitem_convert_async_functions_to_subclass( collector: Union[pytest.Module, pytest.Class], name: str, obj: object -) -> Generator[None, Any, None]: +) -> Generator[None, pluggy.Result, None]: """ Converts coroutines and async generators collected as pytest.Functions to AsyncFunction items. From 59afabfe94b763c6f71b65f3b3e1bc96cdfc6d76 Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Wed, 7 Aug 2024 14:40:35 +0200 Subject: [PATCH 043/226] refactor: Narrowed down return type of pytest_fixture_setup. --- pytest_asyncio/plugin.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pytest_asyncio/plugin.py b/pytest_asyncio/plugin.py index a653ace5..178fcaa6 100644 --- a/pytest_asyncio/plugin.py +++ b/pytest_asyncio/plugin.py @@ -756,11 +756,10 @@ def pytest_generate_tests(metafunc: Metafunc) -> None: ) -# TODO: #778 Narrow down return type of function when dropping support for pytest 7 @pytest.hookimpl(hookwrapper=True) def pytest_fixture_setup( fixturedef: FixtureDef, -) -> Generator[None, Any, None]: +) -> Generator[None, pluggy.Result, None]: """Adjust the event loop policy when an event loop is produced.""" if fixturedef.argname == "event_loop": # The use of a fixture finalizer is preferred over the From d587a521a4aab33275c1352f7832e5e21c4bab93 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 12 Aug 2024 22:27:14 +0000 Subject: [PATCH 044/226] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/rhysd/actionlint: v1.6.22 → v1.7.1](https://github.com/rhysd/actionlint/compare/v1.6.22...v1.7.1) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6ac3ce3e..2ad9e702 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -53,7 +53,7 @@ repos: hooks: - id: python-use-type-annotations - repo: https://github.com/rhysd/actionlint - rev: v1.6.22 + rev: v1.7.1 hooks: - id: actionlint-docker args: From 972a7045adcaff98a151ec632a9205497afe373d Mon Sep 17 00:00:00 2001 From: Kartik Kumar Date: Mon, 12 Aug 2024 13:20:41 +0530 Subject: [PATCH 045/226] Derive project version using importlib --- docs/source/conf.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 4bb6535d..62a48a45 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -6,10 +6,12 @@ # -- Project information ----------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information +import importlib.metadata + project = "pytest-asyncio" copyright = "2023, pytest-asyncio contributors" author = "Tin Tvrtković" -release = "v0.23.0" +release = importlib.metadata.version(project) # -- General configuration --------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration From ae30dac2f7b9af62f3ef7ef614a5c99284a94271 Mon Sep 17 00:00:00 2001 From: Kartik Kumar Date: Mon, 12 Aug 2024 19:10:17 +0530 Subject: [PATCH 046/226] Update .readthedocs.yaml to install pytest-asyncio --- .readthedocs.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index d825e855..efff237b 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -16,3 +16,4 @@ python: install: - requirements: dependencies/default/constraints.txt - requirements: dependencies/docs/constraints.txt + - path: . From 574f1db6869146163cd21b65545494cf517712e2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Aug 2024 18:23:29 +0000 Subject: [PATCH 047/226] Build(deps): Bump babel from 2.15.0 to 2.16.0 in /dependencies/docs Bumps [babel](https://github.com/python-babel/babel) from 2.15.0 to 2.16.0. - [Release notes](https://github.com/python-babel/babel/releases) - [Changelog](https://github.com/python-babel/babel/blob/master/CHANGES.rst) - [Commits](https://github.com/python-babel/babel/compare/v2.15.0...v2.16.0) --- updated-dependencies: - dependency-name: babel dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- dependencies/docs/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/docs/constraints.txt b/dependencies/docs/constraints.txt index dffb4bf5..6df3c716 100644 --- a/dependencies/docs/constraints.txt +++ b/dependencies/docs/constraints.txt @@ -1,5 +1,5 @@ alabaster==0.7.16 -Babel==2.15.0 +Babel==2.16.0 certifi==2024.7.4 charset-normalizer==3.3.2 docutils==0.20.1 From b0ccfc5c5c196bec373fab247565e0158ff39582 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Aug 2024 18:31:04 +0000 Subject: [PATCH 048/226] Build(deps): Bump hypothesis in /dependencies/default Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.108.9 to 6.111.0. - [Release notes](https://github.com/HypothesisWorks/hypothesis/releases) - [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.108.9...hypothesis-python-6.111.0) --- updated-dependencies: - dependency-name: hypothesis dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index 98720d47..ba90a6d2 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -1,7 +1,7 @@ attrs==24.1.0 coverage==7.6.1 exceptiongroup==1.2.2 -hypothesis==6.108.9 +hypothesis==6.111.0 iniconfig==2.0.0 packaging==24.1 pluggy==1.5.0 From 69540bfae3865ebb0395a549cf469fb07c04c08a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Aug 2024 18:31:08 +0000 Subject: [PATCH 049/226] Build(deps): Bump attrs from 24.1.0 to 24.2.0 in /dependencies/default Bumps [attrs](https://github.com/sponsors/hynek) from 24.1.0 to 24.2.0. - [Commits](https://github.com/sponsors/hynek/commits) --- updated-dependencies: - dependency-name: attrs dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index ba90a6d2..36169221 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -1,4 +1,4 @@ -attrs==24.1.0 +attrs==24.2.0 coverage==7.6.1 exceptiongroup==1.2.2 hypothesis==6.111.0 From f03cf13b05f08b8a27f9f33ae578d1caec896d72 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Aug 2024 18:14:20 +0000 Subject: [PATCH 050/226] Build(deps): Bump hypothesis in /dependencies/default Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.111.0 to 6.111.1. - [Release notes](https://github.com/HypothesisWorks/hypothesis/releases) - [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.111.0...hypothesis-python-6.111.1) --- updated-dependencies: - dependency-name: hypothesis dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index 36169221..1221d3b9 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -1,7 +1,7 @@ attrs==24.2.0 coverage==7.6.1 exceptiongroup==1.2.2 -hypothesis==6.111.0 +hypothesis==6.111.1 iniconfig==2.0.0 packaging==24.1 pluggy==1.5.0 From 1bfc18164693026d897ebb48ed6e72d85d87fa44 Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Wed, 14 Aug 2024 01:15:52 +0200 Subject: [PATCH 051/226] Wire Sphinx builds into the RTD config via tox Resolves #917 Adjust test paths to new doc location. --- .readthedocs.yaml | 38 +++++++++++------- docs/Makefile | 20 ---------- docs/{source => }/concepts.rst | 0 .../concepts_function_scope_example.py | 0 .../concepts_module_scope_example.py | 0 docs/{source => }/conf.py | 0 .../change_default_fixture_loop.rst | 0 .../how-to-guides/change_fixture_loop.rst | 0 .../change_fixture_loop_example.py | 0 .../class_scoped_loop_example.py | 0 docs/{source => }/how-to-guides/index.rst | 0 .../module_scoped_loop_example.py | 0 .../how-to-guides/multiple_loops.rst | 0 .../how-to-guides/multiple_loops_example.py | 0 .../package_scoped_loop_example.py | 0 .../run_class_tests_in_same_loop.rst | 0 .../run_module_tests_in_same_loop.rst | 0 .../run_package_tests_in_same_loop.rst | 0 .../run_session_tests_in_same_loop.rst | 0 .../session_scoped_loop_example.py | 0 .../how-to-guides/test_item_is_async.rst | 0 .../test_item_is_async_example.py | 0 .../test_session_scoped_loop_example.py | 0 docs/{source => }/how-to-guides/uvloop.rst | 0 docs/{source => }/index.rst | 0 docs/make.bat | 35 ---------------- docs/{source => }/reference/changelog.rst | 0 docs/{source => }/reference/configuration.rst | 0 .../reference/decorators/index.rst | 0 .../pytest_asyncio_fixture_example.py | 0 .../reference/fixtures/event_loop_example.py | 0 .../fixtures/event_loop_policy_example.py | 0 .../event_loop_policy_parametrized_example.py | 0 .../{source => }/reference/fixtures/index.rst | 0 docs/{source => }/reference/functions.rst | 0 docs/{source => }/reference/index.rst | 0 ...oop_custom_policies_strict_mode_example.py | 0 .../class_scoped_loop_strict_mode_example.py | 0 ...d_loop_with_fixture_strict_mode_example.py | 0 ...ped_loop_pytestmark_strict_mode_example.py | 0 ...unction_scoped_loop_strict_mode_example.py | 0 docs/{source => }/reference/markers/index.rst | 0 .../module_scoped_loop_strict_mode_example.py | 0 docs/{source => }/support.rst | 0 setup.cfg | 2 +- tox.ini | 40 +++++++++++++++++-- 46 files changed, 62 insertions(+), 73 deletions(-) delete mode 100644 docs/Makefile rename docs/{source => }/concepts.rst (100%) rename docs/{source => }/concepts_function_scope_example.py (100%) rename docs/{source => }/concepts_module_scope_example.py (100%) rename docs/{source => }/conf.py (100%) rename docs/{source => }/how-to-guides/change_default_fixture_loop.rst (100%) rename docs/{source => }/how-to-guides/change_fixture_loop.rst (100%) rename docs/{source => }/how-to-guides/change_fixture_loop_example.py (100%) rename docs/{source => }/how-to-guides/class_scoped_loop_example.py (100%) rename docs/{source => }/how-to-guides/index.rst (100%) rename docs/{source => }/how-to-guides/module_scoped_loop_example.py (100%) rename docs/{source => }/how-to-guides/multiple_loops.rst (100%) rename docs/{source => }/how-to-guides/multiple_loops_example.py (100%) rename docs/{source => }/how-to-guides/package_scoped_loop_example.py (100%) rename docs/{source => }/how-to-guides/run_class_tests_in_same_loop.rst (100%) rename docs/{source => }/how-to-guides/run_module_tests_in_same_loop.rst (100%) rename docs/{source => }/how-to-guides/run_package_tests_in_same_loop.rst (100%) rename docs/{source => }/how-to-guides/run_session_tests_in_same_loop.rst (100%) rename docs/{source => }/how-to-guides/session_scoped_loop_example.py (100%) rename docs/{source => }/how-to-guides/test_item_is_async.rst (100%) rename docs/{source => }/how-to-guides/test_item_is_async_example.py (100%) rename docs/{source => }/how-to-guides/test_session_scoped_loop_example.py (100%) rename docs/{source => }/how-to-guides/uvloop.rst (100%) rename docs/{source => }/index.rst (100%) delete mode 100644 docs/make.bat rename docs/{source => }/reference/changelog.rst (100%) rename docs/{source => }/reference/configuration.rst (100%) rename docs/{source => }/reference/decorators/index.rst (100%) rename docs/{source => }/reference/decorators/pytest_asyncio_fixture_example.py (100%) rename docs/{source => }/reference/fixtures/event_loop_example.py (100%) rename docs/{source => }/reference/fixtures/event_loop_policy_example.py (100%) rename docs/{source => }/reference/fixtures/event_loop_policy_parametrized_example.py (100%) rename docs/{source => }/reference/fixtures/index.rst (100%) rename docs/{source => }/reference/functions.rst (100%) rename docs/{source => }/reference/index.rst (100%) rename docs/{source => }/reference/markers/class_scoped_loop_custom_policies_strict_mode_example.py (100%) rename docs/{source => }/reference/markers/class_scoped_loop_strict_mode_example.py (100%) rename docs/{source => }/reference/markers/class_scoped_loop_with_fixture_strict_mode_example.py (100%) rename docs/{source => }/reference/markers/function_scoped_loop_pytestmark_strict_mode_example.py (100%) rename docs/{source => }/reference/markers/function_scoped_loop_strict_mode_example.py (100%) rename docs/{source => }/reference/markers/index.rst (100%) rename docs/{source => }/reference/markers/module_scoped_loop_strict_mode_example.py (100%) rename docs/{source => }/support.rst (100%) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index efff237b..8ffb4b25 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -1,19 +1,29 @@ --- -# Read the Docs configuration file for Sphinx projects -# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details version: 2 + build: - os: ubuntu-22.04 + os: ubuntu-24.04 tools: - python: '3.12' - -sphinx: - configuration: docs/source/conf.py - fail_on_warning: true - -python: - install: - - requirements: dependencies/default/constraints.txt - - requirements: dependencies/docs/constraints.txt - - path: . + python: >- + 3.12 + commands: + - >- + PYTHONWARNINGS=error + python3 -Im venv "${READTHEDOCS_VIRTUALENV_PATH}" + - >- + PYTHONWARNINGS=error + "${READTHEDOCS_VIRTUALENV_PATH}"/bin/python -Im + pip install tox + - >- + PYTHONWARNINGS=error + "${READTHEDOCS_VIRTUALENV_PATH}"/bin/python -Im + tox -e docs --notest -vvvvv + - >- + PYTHONWARNINGS=error + "${READTHEDOCS_VIRTUALENV_PATH}"/bin/python -Im + tox -e docs --skip-pkg-install -q + -- + "${READTHEDOCS_OUTPUT}"/html + -b html + -D language=en diff --git a/docs/Makefile b/docs/Makefile deleted file mode 100644 index d0c3cbf1..00000000 --- a/docs/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# Minimal makefile for Sphinx documentation -# - -# You can set these variables from the command line, and also -# from the environment for the first two. -SPHINXOPTS ?= -SPHINXBUILD ?= sphinx-build -SOURCEDIR = source -BUILDDIR = build - -# Put it first so that "make" without argument is like "make help". -help: - @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) - -.PHONY: help Makefile - -# Catch-all target: route all unknown targets to Sphinx using the new -# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). -%: Makefile - @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/source/concepts.rst b/docs/concepts.rst similarity index 100% rename from docs/source/concepts.rst rename to docs/concepts.rst diff --git a/docs/source/concepts_function_scope_example.py b/docs/concepts_function_scope_example.py similarity index 100% rename from docs/source/concepts_function_scope_example.py rename to docs/concepts_function_scope_example.py diff --git a/docs/source/concepts_module_scope_example.py b/docs/concepts_module_scope_example.py similarity index 100% rename from docs/source/concepts_module_scope_example.py rename to docs/concepts_module_scope_example.py diff --git a/docs/source/conf.py b/docs/conf.py similarity index 100% rename from docs/source/conf.py rename to docs/conf.py diff --git a/docs/source/how-to-guides/change_default_fixture_loop.rst b/docs/how-to-guides/change_default_fixture_loop.rst similarity index 100% rename from docs/source/how-to-guides/change_default_fixture_loop.rst rename to docs/how-to-guides/change_default_fixture_loop.rst diff --git a/docs/source/how-to-guides/change_fixture_loop.rst b/docs/how-to-guides/change_fixture_loop.rst similarity index 100% rename from docs/source/how-to-guides/change_fixture_loop.rst rename to docs/how-to-guides/change_fixture_loop.rst diff --git a/docs/source/how-to-guides/change_fixture_loop_example.py b/docs/how-to-guides/change_fixture_loop_example.py similarity index 100% rename from docs/source/how-to-guides/change_fixture_loop_example.py rename to docs/how-to-guides/change_fixture_loop_example.py diff --git a/docs/source/how-to-guides/class_scoped_loop_example.py b/docs/how-to-guides/class_scoped_loop_example.py similarity index 100% rename from docs/source/how-to-guides/class_scoped_loop_example.py rename to docs/how-to-guides/class_scoped_loop_example.py diff --git a/docs/source/how-to-guides/index.rst b/docs/how-to-guides/index.rst similarity index 100% rename from docs/source/how-to-guides/index.rst rename to docs/how-to-guides/index.rst diff --git a/docs/source/how-to-guides/module_scoped_loop_example.py b/docs/how-to-guides/module_scoped_loop_example.py similarity index 100% rename from docs/source/how-to-guides/module_scoped_loop_example.py rename to docs/how-to-guides/module_scoped_loop_example.py diff --git a/docs/source/how-to-guides/multiple_loops.rst b/docs/how-to-guides/multiple_loops.rst similarity index 100% rename from docs/source/how-to-guides/multiple_loops.rst rename to docs/how-to-guides/multiple_loops.rst diff --git a/docs/source/how-to-guides/multiple_loops_example.py b/docs/how-to-guides/multiple_loops_example.py similarity index 100% rename from docs/source/how-to-guides/multiple_loops_example.py rename to docs/how-to-guides/multiple_loops_example.py diff --git a/docs/source/how-to-guides/package_scoped_loop_example.py b/docs/how-to-guides/package_scoped_loop_example.py similarity index 100% rename from docs/source/how-to-guides/package_scoped_loop_example.py rename to docs/how-to-guides/package_scoped_loop_example.py diff --git a/docs/source/how-to-guides/run_class_tests_in_same_loop.rst b/docs/how-to-guides/run_class_tests_in_same_loop.rst similarity index 100% rename from docs/source/how-to-guides/run_class_tests_in_same_loop.rst rename to docs/how-to-guides/run_class_tests_in_same_loop.rst diff --git a/docs/source/how-to-guides/run_module_tests_in_same_loop.rst b/docs/how-to-guides/run_module_tests_in_same_loop.rst similarity index 100% rename from docs/source/how-to-guides/run_module_tests_in_same_loop.rst rename to docs/how-to-guides/run_module_tests_in_same_loop.rst diff --git a/docs/source/how-to-guides/run_package_tests_in_same_loop.rst b/docs/how-to-guides/run_package_tests_in_same_loop.rst similarity index 100% rename from docs/source/how-to-guides/run_package_tests_in_same_loop.rst rename to docs/how-to-guides/run_package_tests_in_same_loop.rst diff --git a/docs/source/how-to-guides/run_session_tests_in_same_loop.rst b/docs/how-to-guides/run_session_tests_in_same_loop.rst similarity index 100% rename from docs/source/how-to-guides/run_session_tests_in_same_loop.rst rename to docs/how-to-guides/run_session_tests_in_same_loop.rst diff --git a/docs/source/how-to-guides/session_scoped_loop_example.py b/docs/how-to-guides/session_scoped_loop_example.py similarity index 100% rename from docs/source/how-to-guides/session_scoped_loop_example.py rename to docs/how-to-guides/session_scoped_loop_example.py diff --git a/docs/source/how-to-guides/test_item_is_async.rst b/docs/how-to-guides/test_item_is_async.rst similarity index 100% rename from docs/source/how-to-guides/test_item_is_async.rst rename to docs/how-to-guides/test_item_is_async.rst diff --git a/docs/source/how-to-guides/test_item_is_async_example.py b/docs/how-to-guides/test_item_is_async_example.py similarity index 100% rename from docs/source/how-to-guides/test_item_is_async_example.py rename to docs/how-to-guides/test_item_is_async_example.py diff --git a/docs/source/how-to-guides/test_session_scoped_loop_example.py b/docs/how-to-guides/test_session_scoped_loop_example.py similarity index 100% rename from docs/source/how-to-guides/test_session_scoped_loop_example.py rename to docs/how-to-guides/test_session_scoped_loop_example.py diff --git a/docs/source/how-to-guides/uvloop.rst b/docs/how-to-guides/uvloop.rst similarity index 100% rename from docs/source/how-to-guides/uvloop.rst rename to docs/how-to-guides/uvloop.rst diff --git a/docs/source/index.rst b/docs/index.rst similarity index 100% rename from docs/source/index.rst rename to docs/index.rst diff --git a/docs/make.bat b/docs/make.bat deleted file mode 100644 index dc1312ab..00000000 --- a/docs/make.bat +++ /dev/null @@ -1,35 +0,0 @@ -@ECHO OFF - -pushd %~dp0 - -REM Command file for Sphinx documentation - -if "%SPHINXBUILD%" == "" ( - set SPHINXBUILD=sphinx-build -) -set SOURCEDIR=source -set BUILDDIR=build - -%SPHINXBUILD% >NUL 2>NUL -if errorlevel 9009 ( - echo. - echo.The 'sphinx-build' command was not found. Make sure you have Sphinx - echo.installed, then set the SPHINXBUILD environment variable to point - echo.to the full path of the 'sphinx-build' executable. Alternatively you - echo.may add the Sphinx directory to PATH. - echo. - echo.If you don't have Sphinx installed, grab it from - echo.https://www.sphinx-doc.org/ - exit /b 1 -) - -if "%1" == "" goto help - -%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% -goto end - -:help -%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% - -:end -popd diff --git a/docs/source/reference/changelog.rst b/docs/reference/changelog.rst similarity index 100% rename from docs/source/reference/changelog.rst rename to docs/reference/changelog.rst diff --git a/docs/source/reference/configuration.rst b/docs/reference/configuration.rst similarity index 100% rename from docs/source/reference/configuration.rst rename to docs/reference/configuration.rst diff --git a/docs/source/reference/decorators/index.rst b/docs/reference/decorators/index.rst similarity index 100% rename from docs/source/reference/decorators/index.rst rename to docs/reference/decorators/index.rst diff --git a/docs/source/reference/decorators/pytest_asyncio_fixture_example.py b/docs/reference/decorators/pytest_asyncio_fixture_example.py similarity index 100% rename from docs/source/reference/decorators/pytest_asyncio_fixture_example.py rename to docs/reference/decorators/pytest_asyncio_fixture_example.py diff --git a/docs/source/reference/fixtures/event_loop_example.py b/docs/reference/fixtures/event_loop_example.py similarity index 100% rename from docs/source/reference/fixtures/event_loop_example.py rename to docs/reference/fixtures/event_loop_example.py diff --git a/docs/source/reference/fixtures/event_loop_policy_example.py b/docs/reference/fixtures/event_loop_policy_example.py similarity index 100% rename from docs/source/reference/fixtures/event_loop_policy_example.py rename to docs/reference/fixtures/event_loop_policy_example.py diff --git a/docs/source/reference/fixtures/event_loop_policy_parametrized_example.py b/docs/reference/fixtures/event_loop_policy_parametrized_example.py similarity index 100% rename from docs/source/reference/fixtures/event_loop_policy_parametrized_example.py rename to docs/reference/fixtures/event_loop_policy_parametrized_example.py diff --git a/docs/source/reference/fixtures/index.rst b/docs/reference/fixtures/index.rst similarity index 100% rename from docs/source/reference/fixtures/index.rst rename to docs/reference/fixtures/index.rst diff --git a/docs/source/reference/functions.rst b/docs/reference/functions.rst similarity index 100% rename from docs/source/reference/functions.rst rename to docs/reference/functions.rst diff --git a/docs/source/reference/index.rst b/docs/reference/index.rst similarity index 100% rename from docs/source/reference/index.rst rename to docs/reference/index.rst diff --git a/docs/source/reference/markers/class_scoped_loop_custom_policies_strict_mode_example.py b/docs/reference/markers/class_scoped_loop_custom_policies_strict_mode_example.py similarity index 100% rename from docs/source/reference/markers/class_scoped_loop_custom_policies_strict_mode_example.py rename to docs/reference/markers/class_scoped_loop_custom_policies_strict_mode_example.py diff --git a/docs/source/reference/markers/class_scoped_loop_strict_mode_example.py b/docs/reference/markers/class_scoped_loop_strict_mode_example.py similarity index 100% rename from docs/source/reference/markers/class_scoped_loop_strict_mode_example.py rename to docs/reference/markers/class_scoped_loop_strict_mode_example.py diff --git a/docs/source/reference/markers/class_scoped_loop_with_fixture_strict_mode_example.py b/docs/reference/markers/class_scoped_loop_with_fixture_strict_mode_example.py similarity index 100% rename from docs/source/reference/markers/class_scoped_loop_with_fixture_strict_mode_example.py rename to docs/reference/markers/class_scoped_loop_with_fixture_strict_mode_example.py diff --git a/docs/source/reference/markers/function_scoped_loop_pytestmark_strict_mode_example.py b/docs/reference/markers/function_scoped_loop_pytestmark_strict_mode_example.py similarity index 100% rename from docs/source/reference/markers/function_scoped_loop_pytestmark_strict_mode_example.py rename to docs/reference/markers/function_scoped_loop_pytestmark_strict_mode_example.py diff --git a/docs/source/reference/markers/function_scoped_loop_strict_mode_example.py b/docs/reference/markers/function_scoped_loop_strict_mode_example.py similarity index 100% rename from docs/source/reference/markers/function_scoped_loop_strict_mode_example.py rename to docs/reference/markers/function_scoped_loop_strict_mode_example.py diff --git a/docs/source/reference/markers/index.rst b/docs/reference/markers/index.rst similarity index 100% rename from docs/source/reference/markers/index.rst rename to docs/reference/markers/index.rst diff --git a/docs/source/reference/markers/module_scoped_loop_strict_mode_example.py b/docs/reference/markers/module_scoped_loop_strict_mode_example.py similarity index 100% rename from docs/source/reference/markers/module_scoped_loop_strict_mode_example.py rename to docs/reference/markers/module_scoped_loop_strict_mode_example.py diff --git a/docs/source/support.rst b/docs/support.rst similarity index 100% rename from docs/source/support.rst rename to docs/support.rst diff --git a/setup.cfg b/setup.cfg index c04d3884..ac2f2adc 100644 --- a/setup.cfg +++ b/setup.cfg @@ -65,7 +65,7 @@ show_missing = true [tool:pytest] python_files = test_*.py *_example.py addopts = -rsx --tb=short -testpaths = docs/source tests +testpaths = docs tests asyncio_mode = auto junit_family=xunit2 filterwarnings = diff --git a/tox.ini b/tox.ini index 665c2fff..79e96fa6 100644 --- a/tox.ini +++ b/tox.ini @@ -26,14 +26,48 @@ allowlist_externals = make [testenv:docs] +allowlist_externals = + git extras = docs deps = --requirement dependencies/docs/requirements.txt --constraint dependencies/docs/constraints.txt change_dir = docs -commands = make html -allowlist_externals = - make +description = Build The Docs with {basepython} +commands = + # Retrieve possibly missing commits: + -git fetch --unshallow + -git fetch --tags + + # Build the html docs with Sphinx: + {envpython} -Im sphinx \ + -j auto \ + {tty:--color} \ + -a \ + -T \ + -n \ + -W --keep-going \ + -d "{temp_dir}{/}.doctrees" \ + . \ + {posargs:"{envdir}{/}docs_out" -b html} + + # Print out the output docs dir and a way to serve html: + -{envpython} -c\ + 'import pathlib;\ + docs_dir = pathlib.Path(r"{envdir}") / "docs_out";\ + index_file = docs_dir / "index.html";\ + print("\n" + "=" * 120 +\ + f"\n\nOpen the documentation with:\n\n\ + \t$ python3 -Im webbrowser \N\{QUOTATION MARK\}file://\{index_file\}\N\{QUOTATION MARK\}\n\n\ + To serve docs, use\n\n\ + \t$ python3 -Im http.server --directory \ + \N\{QUOTATION MARK\}\{docs_dir\}\N\{QUOTATION MARK\} 0\n\n" +\ + "=" * 120)' +changedir = {toxinidir}{/}docs +isolated_build = true +passenv = + SSH_AUTH_SOCK +skip_install = false [gh-actions] python = From 6dc7f584e71476c09393cca65c813c624ecc5882 Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Tue, 13 Aug 2024 12:53:13 +0200 Subject: [PATCH 052/226] docs: Add migration guides for pytest-asyncio v0.21 and v0.23. --- docs/how-to-guides/index.rst | 2 ++ docs/how-to-guides/migrate_from_0_21.rst | 17 +++++++++++++++++ docs/how-to-guides/migrate_from_0_23.rst | 8 ++++++++ 3 files changed, 27 insertions(+) create mode 100644 docs/how-to-guides/migrate_from_0_21.rst create mode 100644 docs/how-to-guides/migrate_from_0_23.rst diff --git a/docs/how-to-guides/index.rst b/docs/how-to-guides/index.rst index 4f03dd35..7b3c4f31 100644 --- a/docs/how-to-guides/index.rst +++ b/docs/how-to-guides/index.rst @@ -5,6 +5,8 @@ How-To Guides .. toctree:: :hidden: + migrate_from_0_21 + migrate_from_0_23 change_fixture_loop change_default_fixture_loop run_class_tests_in_same_loop diff --git a/docs/how-to-guides/migrate_from_0_21.rst b/docs/how-to-guides/migrate_from_0_21.rst new file mode 100644 index 00000000..a244ad1f --- /dev/null +++ b/docs/how-to-guides/migrate_from_0_21.rst @@ -0,0 +1,17 @@ +.. _how_to_guides/migrate_from_0_21: + +======================================== +How to migrate from pytest-asyncio v0.21 +======================================== +1. If your test suite re-implements the *event_loop* fixture, make sure the fixture implementations don't do anything besides creating a new asyncio event loop, yielding it, and closing it. +2. Convert all synchronous test cases requesting the *event_loop* fixture to asynchronous test cases. +3. Convert all synchronous fixtures requesting the *event_loop* fixture to asynchronous fixtures. +4. Remove the *event_loop* argument from all asynchronous test cases in favor of ``event_loop = asyncio.get_running_loop()``. +5. Remove the *event_loop* argument from all asynchronous fixtures in favor of ``event_loop = asyncio.get_running_loop()``. + +Go through all re-implemented *event_loop* fixtures in your test suite one by one, starting with the the fixture with the deepest nesting level and take note of the fixture scope: + +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 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. diff --git a/docs/how-to-guides/migrate_from_0_23.rst b/docs/how-to-guides/migrate_from_0_23.rst new file mode 100644 index 00000000..1235f358 --- /dev/null +++ b/docs/how-to-guides/migrate_from_0_23.rst @@ -0,0 +1,8 @@ +======================================== +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. ` + +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. +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. From fb5422f94d4a85b8f2a0ea2731f5ebeae5fcd7e8 Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Thu, 22 Aug 2024 09:42:19 +0200 Subject: [PATCH 053/226] docs: Set release date for v0.24 in changelog. --- docs/reference/changelog.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference/changelog.rst b/docs/reference/changelog.rst index abf27a0a..77cf3451 100644 --- a/docs/reference/changelog.rst +++ b/docs/reference/changelog.rst @@ -2,7 +2,7 @@ Changelog ========= -0.24.0 (UNRELEASED) +0.24.0 (2024-08-22) =================== - BREAKING: Updated minimum supported pytest version to v8.2.0 - Adds an optional `loop_scope` keyword argument to `pytest.mark.asyncio`. This argument controls which event loop is used to run the marked async test. `#706`_, `#871 `_ From 552a745a0e312980e768cad73a58b9c33a11c199 Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Fri, 23 Aug 2024 08:58:53 +0200 Subject: [PATCH 054/226] refactor: Set default asyncio event loop for fixtures in setup.cfg --- .../class_scoped_loop_with_fixture_strict_mode_example.py | 2 +- setup.cfg | 1 + tests/async_fixtures/test_async_fixtures_with_finalizer.py | 6 ++++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/reference/markers/class_scoped_loop_with_fixture_strict_mode_example.py b/docs/reference/markers/class_scoped_loop_with_fixture_strict_mode_example.py index 239f3968..6fff0af8 100644 --- a/docs/reference/markers/class_scoped_loop_with_fixture_strict_mode_example.py +++ b/docs/reference/markers/class_scoped_loop_with_fixture_strict_mode_example.py @@ -9,7 +9,7 @@ class TestClassScopedLoop: loop: asyncio.AbstractEventLoop - @pytest_asyncio.fixture(scope="class") + @pytest_asyncio.fixture(loop_scope="class") async def my_fixture(self): TestClassScopedLoop.loop = asyncio.get_running_loop() diff --git a/setup.cfg b/setup.cfg index ac2f2adc..00c6bdd4 100644 --- a/setup.cfg +++ b/setup.cfg @@ -67,6 +67,7 @@ python_files = test_*.py *_example.py addopts = -rsx --tb=short testpaths = docs tests asyncio_mode = auto +asyncio_default_fixture_loop_scope = function junit_family=xunit2 filterwarnings = error diff --git a/tests/async_fixtures/test_async_fixtures_with_finalizer.py b/tests/async_fixtures/test_async_fixtures_with_finalizer.py index bc6826bb..8efc8fc4 100644 --- a/tests/async_fixtures/test_async_fixtures_with_finalizer.py +++ b/tests/async_fixtures/test_async_fixtures_with_finalizer.py @@ -3,6 +3,8 @@ import pytest +import pytest_asyncio + @pytest.mark.asyncio(loop_scope="module") async def test_module_with_event_loop_finalizer(port_with_event_loop_finalizer): @@ -25,7 +27,7 @@ def event_loop(): loop.close() -@pytest.fixture(scope="module") +@pytest_asyncio.fixture(loop_scope="module", scope="module") async def port_with_event_loop_finalizer(request): def port_finalizer(finalizer): async def port_afinalizer(): @@ -40,7 +42,7 @@ async def port_afinalizer(): return True -@pytest.fixture(scope="module") +@pytest_asyncio.fixture(loop_scope="module", scope="module") async def port_with_get_event_loop_finalizer(request): def port_finalizer(finalizer): async def port_afinalizer(): From 7a8586ab3a5a85f02f0d3d421b2b7a148cb4d997 Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Fri, 23 Aug 2024 09:37:27 +0200 Subject: [PATCH 055/226] refactor: Addressed warning about missing default fixture scope configuration in tests/async_fixtures/test_shared_module_fixture.py --- tests/async_fixtures/test_shared_module_fixture.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/async_fixtures/test_shared_module_fixture.py b/tests/async_fixtures/test_shared_module_fixture.py index ff1cb62b..9b0ad540 100644 --- a/tests/async_fixtures/test_shared_module_fixture.py +++ b/tests/async_fixtures/test_shared_module_fixture.py @@ -4,12 +4,13 @@ def test_asyncio_mark_provides_package_scoped_loop_strict_mode(pytester: Pytester): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( __init__="", conftest=dedent( """\ import pytest_asyncio - @pytest_asyncio.fixture(scope="module") + @pytest_asyncio.fixture(loop_scope="module", scope="module") async def async_shared_module_fixture(): return True """ From dd4e982c02eff5f8b4b7f82ae83e045db2a8b8e9 Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Fri, 23 Aug 2024 09:42:06 +0200 Subject: [PATCH 056/226] refactor: Addressed warning about missing default fixture loop scope in Hypothesis tests. --- tests/hypothesis/test_base.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/hypothesis/test_base.py b/tests/hypothesis/test_base.py index 2d2171bd..176c9aee 100644 --- a/tests/hypothesis/test_base.py +++ b/tests/hypothesis/test_base.py @@ -10,6 +10,7 @@ def test_hypothesis_given_decorator_before_asyncio_mark(pytester: Pytester): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -42,6 +43,7 @@ async def test_mark_and_parametrize(x, y): def test_can_use_explicit_event_loop_fixture(pytester: Pytester): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = module") pytester.makepyfile( dedent( """\ @@ -78,6 +80,7 @@ async def test_explicit_fixture_request(event_loop, n): def test_async_auto_marked(pytester: Pytester): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -100,6 +103,7 @@ async def test_hypothesis(n: int): def test_sync_not_auto_marked(pytester: Pytester): """Assert that synchronous Hypothesis functions are not marked with asyncio""" + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ From 3de231eedbebd61a08e6b1a441d578806fc68c59 Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Fri, 23 Aug 2024 09:52:23 +0200 Subject: [PATCH 057/226] refactor: Addressed warnings about missing default fixture loop in tests/markers/test_class_scope.py. --- tests/markers/test_class_scope.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/tests/markers/test_class_scope.py b/tests/markers/test_class_scope.py index baac5869..edce31f6 100644 --- a/tests/markers/test_class_scope.py +++ b/tests/markers/test_class_scope.py @@ -30,6 +30,7 @@ def sample_fixture(): def test_asyncio_mark_provides_class_scoped_loop_when_applied_to_functions( pytester: pytest.Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -56,6 +57,7 @@ async def test_this_runs_in_same_loop(self): def test_asyncio_mark_provides_class_scoped_loop_when_applied_to_class( pytester: pytest.Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -81,6 +83,7 @@ async def test_this_runs_in_same_loop(self): def test_asyncio_mark_raises_when_class_scoped_is_request_without_class( pytester: pytest.Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -101,6 +104,7 @@ async def test_has_no_surrounding_class(): def test_asyncio_mark_is_inherited_to_subclasses(pytester: pytest.Pytester): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -129,6 +133,7 @@ async def test_this_runs_in_same_loop(self): def test_asyncio_mark_respects_the_loop_policy( pytester: pytest.Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -166,6 +171,7 @@ async def test_does_not_use_custom_event_loop_policy(): def test_asyncio_mark_respects_parametrized_loop_policies( pytester: pytest.Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -197,6 +203,7 @@ async def test_parametrized_loop(self, request): def test_asyncio_mark_provides_class_scoped_loop_to_fixtures( pytester: pytest.Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -226,6 +233,7 @@ async def test_runs_is_same_loop_as_fixture(self, my_fixture): def test_asyncio_mark_allows_combining_class_scoped_fixture_with_function_scoped_test( pytester: pytest.Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -237,7 +245,7 @@ def test_asyncio_mark_allows_combining_class_scoped_fixture_with_function_scoped loop: asyncio.AbstractEventLoop class TestMixedScopes: - @pytest_asyncio.fixture(scope="class") + @pytest_asyncio.fixture(loop_scope="class", scope="class") async def async_fixture(self): global loop loop = asyncio.get_running_loop() @@ -257,6 +265,7 @@ async def test_runs_in_different_loop_as_fixture(self, async_fixture): def test_asyncio_mark_handles_missing_event_loop_triggered_by_fixture( pytester: pytest.Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -292,6 +301,7 @@ async def test_does_not_fail(self, sets_event_loop_to_none, n): def test_standalone_test_does_not_trigger_warning_about_no_current_event_loop_being_set( pytester: pytest.Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ From e8570f2d5228003364294a6ed1945e75326d2cfa Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Fri, 23 Aug 2024 09:57:03 +0200 Subject: [PATCH 058/226] refactor: Addressed warnings about missing default fixture loop in tests/markers/test_function_scope.py. --- tests/markers/test_function_scope.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/markers/test_function_scope.py b/tests/markers/test_function_scope.py index 81260006..75487b5d 100644 --- a/tests/markers/test_function_scope.py +++ b/tests/markers/test_function_scope.py @@ -4,6 +4,7 @@ def test_asyncio_mark_provides_function_scoped_loop_strict_mode(pytester: Pytester): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -29,6 +30,7 @@ async def test_does_not_run_in_same_loop(): def test_loop_scope_function_provides_function_scoped_event_loop(pytester: Pytester): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -54,6 +56,7 @@ async def test_does_not_run_in_same_loop(): def test_raises_when_scope_and_loop_scope_arguments_are_present(pytester: Pytester): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -70,6 +73,7 @@ async def test_raises(): def test_warns_when_scope_argument_is_present(pytester: Pytester): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -89,6 +93,7 @@ async def test_warns(): def test_function_scope_supports_explicit_event_loop_fixture_request( pytester: Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -111,6 +116,7 @@ async def test_remember_loop(event_loop): def test_asyncio_mark_respects_the_loop_policy( pytester: Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -141,6 +147,7 @@ async def test_uses_custom_event_loop_policy(): def test_asyncio_mark_respects_parametrized_loop_policies( pytester: Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -178,6 +185,7 @@ async def test_parametrized_loop(): def test_asyncio_mark_provides_function_scoped_loop_to_fixtures( pytester: Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -208,6 +216,7 @@ async def test_runs_is_same_loop_as_fixture(my_fixture): def test_asyncio_mark_handles_missing_event_loop_triggered_by_fixture( pytester: Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -242,6 +251,7 @@ async def test_does_not_fail(sets_event_loop_to_none, n): def test_standalone_test_does_not_trigger_warning_about_no_current_event_loop_being_set( pytester: Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -260,6 +270,7 @@ async def test_anything(): def test_asyncio_mark_does_not_duplicate_other_marks_in_auto_mode( pytester: Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makeconftest( dedent( """\ From 1f75ca73506d756867fb9db3e472f3c8a823efd7 Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Fri, 23 Aug 2024 10:05:20 +0200 Subject: [PATCH 059/226] refactor: Addressed warnings about missing default fixture loop scope in tests/markers/test_module_scope.py. --- tests/markers/test_module_scope.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/tests/markers/test_module_scope.py b/tests/markers/test_module_scope.py index 5280ed7e..12515f23 100644 --- a/tests/markers/test_module_scope.py +++ b/tests/markers/test_module_scope.py @@ -4,6 +4,7 @@ def test_asyncio_mark_works_on_module_level(pytester: Pytester): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -56,6 +57,7 @@ def sample_fixture(): def test_asyncio_mark_provides_module_scoped_loop_strict_mode(pytester: Pytester): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -88,6 +90,7 @@ async def test_this_runs_in_same_loop(self): def test_raise_when_event_loop_fixture_is_requested_in_addition_to_scoped_loop( pytester: Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -109,6 +112,7 @@ async def test_remember_loop(event_loop): def test_asyncio_mark_respects_the_loop_policy( pytester: Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( __init__="", custom_policy=dedent( @@ -163,6 +167,7 @@ async def test_does_not_use_custom_event_loop_policy(): def test_asyncio_mark_respects_parametrized_loop_policies( pytester: Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -194,6 +199,7 @@ async def test_parametrized_loop(): def test_asyncio_mark_provides_module_scoped_loop_to_fixtures( pytester: Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -206,7 +212,7 @@ def test_asyncio_mark_provides_module_scoped_loop_to_fixtures( loop: asyncio.AbstractEventLoop - @pytest_asyncio.fixture(scope="module") + @pytest_asyncio.fixture(loop_scope="module", scope="module") async def my_fixture(): global loop loop = asyncio.get_running_loop() @@ -224,6 +230,7 @@ async def test_runs_is_same_loop_as_fixture(my_fixture): def test_asyncio_mark_allows_combining_module_scoped_fixture_with_class_scoped_test( pytester: Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -234,7 +241,7 @@ def test_asyncio_mark_allows_combining_module_scoped_fixture_with_class_scoped_t loop: asyncio.AbstractEventLoop - @pytest_asyncio.fixture(scope="module") + @pytest_asyncio.fixture(loop_scope="module", scope="module") async def async_fixture(): global loop loop = asyncio.get_running_loop() @@ -255,6 +262,7 @@ async def test_runs_in_different_loop_as_fixture(self, async_fixture): def test_asyncio_mark_allows_combining_module_scoped_fixture_with_function_scoped_test( pytester: Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( __init__="", test_mixed_scopes=dedent( @@ -266,7 +274,7 @@ def test_asyncio_mark_allows_combining_module_scoped_fixture_with_function_scope loop: asyncio.AbstractEventLoop - @pytest_asyncio.fixture(scope="module") + @pytest_asyncio.fixture(loop_scope="module", scope="module") async def async_fixture(): global loop loop = asyncio.get_running_loop() @@ -285,6 +293,7 @@ async def test_runs_in_different_loop_as_fixture(async_fixture): def test_allows_combining_module_scoped_asyncgen_fixture_with_function_scoped_test( pytester: Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -295,7 +304,7 @@ def test_allows_combining_module_scoped_asyncgen_fixture_with_function_scoped_te loop: asyncio.AbstractEventLoop - @pytest_asyncio.fixture(scope="module") + @pytest_asyncio.fixture(loop_scope="module", scope="module") async def async_fixture(): global loop loop = asyncio.get_running_loop() @@ -315,6 +324,7 @@ async def test_runs_in_different_loop_as_fixture(async_fixture): def test_asyncio_mark_handles_missing_event_loop_triggered_by_fixture( pytester: Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -349,6 +359,7 @@ async def test_does_not_fail(sets_event_loop_to_none, n): def test_standalone_test_does_not_trigger_warning_about_no_current_event_loop_being_set( pytester: Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ From d688f7a77fb5b708f9721acbb8a5ccf7e3706477 Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Fri, 23 Aug 2024 10:10:42 +0200 Subject: [PATCH 060/226] refactor: Addressed warnings about missing default fixture loop scope in tests/markers/test_package_scope.py. --- tests/markers/test_package_scope.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/tests/markers/test_package_scope.py b/tests/markers/test_package_scope.py index 849967e8..bd3e4ac7 100644 --- a/tests/markers/test_package_scope.py +++ b/tests/markers/test_package_scope.py @@ -6,6 +6,7 @@ def test_asyncio_mark_provides_package_scoped_loop_strict_mode(pytester: Pytester): package_name = pytester.path.name subpackage_name = "subpkg" + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( __init__="", shared_module=dedent( @@ -69,6 +70,7 @@ async def test_subpackage_runs_in_different_loop(): def test_raise_when_event_loop_fixture_is_requested_in_addition_to_scoped_loop( pytester: Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( __init__="", test_raises=dedent( @@ -90,6 +92,7 @@ async def test_remember_loop(event_loop): def test_asyncio_mark_respects_the_loop_policy( pytester: Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( __init__="", conftest=dedent( @@ -151,6 +154,7 @@ async def test_also_uses_custom_event_loop_policy(): def test_asyncio_mark_respects_parametrized_loop_policies( pytester: Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( __init__="", test_parametrization=dedent( @@ -183,6 +187,7 @@ async def test_parametrized_loop(): def test_asyncio_mark_provides_package_scoped_loop_to_fixtures( pytester: Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") package_name = pytester.path.name pytester.makepyfile( __init__="", @@ -194,7 +199,7 @@ def test_asyncio_mark_provides_package_scoped_loop_to_fixtures( from {package_name} import shared_module - @pytest_asyncio.fixture(scope="package") + @pytest_asyncio.fixture(loop_scope="package", scope="package") async def my_fixture(): shared_module.loop = asyncio.get_running_loop() """ @@ -229,6 +234,7 @@ async def test_runs_in_same_loop_as_fixture(my_fixture): def test_asyncio_mark_allows_combining_package_scoped_fixture_with_module_scoped_test( pytester: Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( __init__="", test_mixed_scopes=dedent( @@ -240,7 +246,7 @@ def test_asyncio_mark_allows_combining_package_scoped_fixture_with_module_scoped loop: asyncio.AbstractEventLoop - @pytest_asyncio.fixture(scope="package") + @pytest_asyncio.fixture(loop_scope="package", scope="package") async def async_fixture(): global loop loop = asyncio.get_running_loop() @@ -259,6 +265,7 @@ async def test_runs_in_different_loop_as_fixture(async_fixture): def test_asyncio_mark_allows_combining_package_scoped_fixture_with_class_scoped_test( pytester: Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( __init__="", test_mixed_scopes=dedent( @@ -270,7 +277,7 @@ def test_asyncio_mark_allows_combining_package_scoped_fixture_with_class_scoped_ loop: asyncio.AbstractEventLoop - @pytest_asyncio.fixture(scope="package") + @pytest_asyncio.fixture(loop_scope="package", scope="package") async def async_fixture(): global loop loop = asyncio.get_running_loop() @@ -290,6 +297,7 @@ async def test_runs_in_different_loop_as_fixture(self, async_fixture): def test_asyncio_mark_allows_combining_package_scoped_fixture_with_function_scoped_test( pytester: Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( __init__="", test_mixed_scopes=dedent( @@ -301,7 +309,7 @@ def test_asyncio_mark_allows_combining_package_scoped_fixture_with_function_scop loop: asyncio.AbstractEventLoop - @pytest_asyncio.fixture(scope="package") + @pytest_asyncio.fixture(loop_scope="package", scope="package") async def async_fixture(): global loop loop = asyncio.get_running_loop() @@ -320,6 +328,7 @@ async def test_runs_in_different_loop_as_fixture(async_fixture): def test_asyncio_mark_handles_missing_event_loop_triggered_by_fixture( pytester: Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( __init__="", test_loop_is_none=dedent( @@ -355,6 +364,7 @@ async def test_does_not_fail(sets_event_loop_to_none, n): def test_standalone_test_does_not_trigger_warning_about_no_current_event_loop_being_set( pytester: Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( __init__="", test_module=dedent( From 1ea2824fd09213081b0bc7e046ead745a49be440 Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Fri, 23 Aug 2024 10:17:55 +0200 Subject: [PATCH 061/226] refactor: Addressed warnings about missing default fixture loop scope in tests/markers/test_session_scope.py. --- tests/markers/test_session_scope.py | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/tests/markers/test_session_scope.py b/tests/markers/test_session_scope.py index 7900ef48..3bc38a4f 100644 --- a/tests/markers/test_session_scope.py +++ b/tests/markers/test_session_scope.py @@ -5,6 +5,7 @@ def test_asyncio_mark_provides_session_scoped_loop_strict_mode(pytester: Pytester): package_name = pytester.path.name + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( __init__="", shared_module=dedent( @@ -70,6 +71,7 @@ async def test_subpackage_runs_in_same_loop(): def test_raise_when_event_loop_fixture_is_requested_in_addition_to_scoped_loop( pytester: Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( __init__="", test_raises=dedent( @@ -91,6 +93,7 @@ async def test_remember_loop(event_loop): def test_asyncio_mark_respects_the_loop_policy( pytester: Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( __init__="", conftest=dedent( @@ -152,6 +155,7 @@ async def test_also_uses_custom_event_loop_policy(): def test_asyncio_mark_respects_parametrized_loop_policies( pytester: Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( __init__="", test_parametrization=dedent( @@ -185,6 +189,7 @@ def test_asyncio_mark_provides_session_scoped_loop_to_fixtures( pytester: Pytester, ): package_name = pytester.path.name + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( __init__="", conftest=dedent( @@ -195,7 +200,7 @@ def test_asyncio_mark_provides_session_scoped_loop_to_fixtures( from {package_name} import shared_module - @pytest_asyncio.fixture(scope="session") + @pytest_asyncio.fixture(loop_scope="session", scope="session") async def my_fixture(): shared_module.loop = asyncio.get_running_loop() """ @@ -234,6 +239,7 @@ async def test_runs_in_same_loop_as_fixture(my_fixture): def test_asyncio_mark_allows_combining_session_scoped_fixture_with_package_scoped_test( pytester: Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( __init__="", test_mixed_scopes=dedent( @@ -245,7 +251,7 @@ def test_asyncio_mark_allows_combining_session_scoped_fixture_with_package_scope loop: asyncio.AbstractEventLoop - @pytest_asyncio.fixture(scope="session") + @pytest_asyncio.fixture(loop_scope="session", scope="session") async def async_fixture(): global loop loop = asyncio.get_running_loop() @@ -264,6 +270,7 @@ async def test_runs_in_different_loop_as_fixture(async_fixture): def test_asyncio_mark_allows_combining_session_scoped_fixture_with_module_scoped_test( pytester: Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( __init__="", test_mixed_scopes=dedent( @@ -275,7 +282,7 @@ def test_asyncio_mark_allows_combining_session_scoped_fixture_with_module_scoped loop: asyncio.AbstractEventLoop - @pytest_asyncio.fixture(scope="session") + @pytest_asyncio.fixture(loop_scope="session", scope="session") async def async_fixture(): global loop loop = asyncio.get_running_loop() @@ -294,6 +301,7 @@ async def test_runs_in_different_loop_as_fixture(async_fixture): def test_asyncio_mark_allows_combining_session_scoped_fixture_with_class_scoped_test( pytester: Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( __init__="", test_mixed_scopes=dedent( @@ -305,7 +313,7 @@ def test_asyncio_mark_allows_combining_session_scoped_fixture_with_class_scoped_ loop: asyncio.AbstractEventLoop - @pytest_asyncio.fixture(scope="session") + @pytest_asyncio.fixture(loop_scope="session", scope="session") async def async_fixture(): global loop loop = asyncio.get_running_loop() @@ -325,6 +333,7 @@ async def test_runs_in_different_loop_as_fixture(self, async_fixture): def test_asyncio_mark_allows_combining_session_scoped_fixture_with_function_scoped_test( pytester: Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( __init__="", test_mixed_scopes=dedent( @@ -336,7 +345,7 @@ def test_asyncio_mark_allows_combining_session_scoped_fixture_with_function_scop loop: asyncio.AbstractEventLoop - @pytest_asyncio.fixture(scope="session") + @pytest_asyncio.fixture(loop_scope="session", scope="session") async def async_fixture(): global loop loop = asyncio.get_running_loop() @@ -355,6 +364,7 @@ async def test_runs_in_different_loop_as_fixture(async_fixture): def test_allows_combining_session_scoped_asyncgen_fixture_with_function_scoped_test( pytester: Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( __init__="", test_mixed_scopes=dedent( @@ -366,7 +376,7 @@ def test_allows_combining_session_scoped_asyncgen_fixture_with_function_scoped_t loop: asyncio.AbstractEventLoop - @pytest_asyncio.fixture(scope="session") + @pytest_asyncio.fixture(loop_scope="session", scope="session") async def async_fixture(): global loop loop = asyncio.get_running_loop() @@ -386,6 +396,7 @@ async def test_runs_in_different_loop_as_fixture(async_fixture): def test_asyncio_mark_handles_missing_event_loop_triggered_by_fixture( pytester: Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -420,6 +431,7 @@ async def test_does_not_fail(sets_event_loop_to_none, n): def test_standalone_test_does_not_trigger_warning_about_no_current_event_loop_being_set( pytester: Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ From a4dffa20de7af62b9cfc88a35b7c40d71ae405e6 Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Fri, 23 Aug 2024 13:00:20 +0200 Subject: [PATCH 062/226] refactor: test_auto_mode uses pytester, instead of testdir. --- tests/modes/test_auto_mode.py | 40 ++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/tests/modes/test_auto_mode.py b/tests/modes/test_auto_mode.py index fc4d2df0..8baa31ea 100644 --- a/tests/modes/test_auto_mode.py +++ b/tests/modes/test_auto_mode.py @@ -1,8 +1,10 @@ from textwrap import dedent +from pytest import Pytester -def test_auto_mode_cmdline(testdir): - testdir.makepyfile( + +def test_auto_mode_cmdline(pytester: Pytester): + pytester.makepyfile( dedent( """\ import asyncio @@ -15,12 +17,12 @@ async def test_a(): """ ) ) - result = testdir.runpytest("--asyncio-mode=auto") + result = pytester.runpytest("--asyncio-mode=auto") result.assert_outcomes(passed=1) -def test_auto_mode_cfg(testdir): - testdir.makepyfile( +def test_auto_mode_cfg(pytester: Pytester): + pytester.makepyfile( dedent( """\ import asyncio @@ -33,13 +35,13 @@ async def test_a(): """ ) ) - testdir.makefile(".ini", pytest="[pytest]\nasyncio_mode = auto\n") - result = testdir.runpytest() + pytester.makefile(".ini", pytest="[pytest]\nasyncio_mode = auto\n") + result = pytester.runpytest() result.assert_outcomes(passed=1) -def test_auto_mode_async_fixture(testdir): - testdir.makepyfile( +def test_auto_mode_async_fixture(pytester: Pytester): + pytester.makepyfile( dedent( """\ import asyncio @@ -58,12 +60,12 @@ async def test_a(fixture_a): """ ) ) - result = testdir.runpytest("--asyncio-mode=auto") + result = pytester.runpytest("--asyncio-mode=auto") result.assert_outcomes(passed=1) -def test_auto_mode_method_fixture(testdir): - testdir.makepyfile( +def test_auto_mode_method_fixture(pytester: Pytester): + pytester.makepyfile( dedent( """\ import asyncio @@ -85,12 +87,12 @@ async def test_a(self, fixture_a): """ ) ) - result = testdir.runpytest("--asyncio-mode=auto") + result = pytester.runpytest("--asyncio-mode=auto") result.assert_outcomes(passed=1) -def test_auto_mode_static_method(testdir): - testdir.makepyfile( +def test_auto_mode_static_method(pytester: Pytester): + pytester.makepyfile( dedent( """\ import asyncio @@ -106,12 +108,12 @@ async def test_a(): """ ) ) - result = testdir.runpytest("--asyncio-mode=auto") + result = pytester.runpytest("--asyncio-mode=auto") result.assert_outcomes(passed=1) -def test_auto_mode_static_method_fixture(testdir): - testdir.makepyfile( +def test_auto_mode_static_method_fixture(pytester: Pytester): + pytester.makepyfile( dedent( """\ import asyncio @@ -135,5 +137,5 @@ async def test_a(fixture_a): """ ) ) - result = testdir.runpytest("--asyncio-mode=auto") + result = pytester.runpytest("--asyncio-mode=auto") result.assert_outcomes(passed=1) From bada7bad2b42fe0f2b7976b31011551177cf53fd Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Fri, 23 Aug 2024 13:09:16 +0200 Subject: [PATCH 063/226] refactor: Addressed warnings about missing default fixture loop scope in tests/modes/test_auto_mode.py. --- tests/modes/test_auto_mode.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/tests/modes/test_auto_mode.py b/tests/modes/test_auto_mode.py index 8baa31ea..f41c9d1a 100644 --- a/tests/modes/test_auto_mode.py +++ b/tests/modes/test_auto_mode.py @@ -4,6 +4,7 @@ def test_auto_mode_cmdline(pytester: Pytester): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -22,6 +23,15 @@ async def test_a(): def test_auto_mode_cfg(pytester: Pytester): + pytester.makeini( + dedent( + """\ + [pytest] + asyncio_default_fixture_loop_scope = function + asyncio_mode = auto + """ + ) + ) pytester.makepyfile( dedent( """\ @@ -35,12 +45,12 @@ async def test_a(): """ ) ) - pytester.makefile(".ini", pytest="[pytest]\nasyncio_mode = auto\n") - result = pytester.runpytest() + result = pytester.runpytest("--asyncio-mode=auto") result.assert_outcomes(passed=1) def test_auto_mode_async_fixture(pytester: Pytester): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -65,6 +75,7 @@ async def test_a(fixture_a): def test_auto_mode_method_fixture(pytester: Pytester): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -92,6 +103,7 @@ async def test_a(self, fixture_a): def test_auto_mode_static_method(pytester: Pytester): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -113,6 +125,7 @@ async def test_a(): def test_auto_mode_static_method_fixture(pytester: Pytester): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ From 11b2854062dc61e9a904657db454e00e37f2aa28 Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Fri, 23 Aug 2024 13:13:22 +0200 Subject: [PATCH 064/226] refactor: Replaced use of testdir with pytester in test_strict_mode. --- tests/modes/test_strict_mode.py | 34 +++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/tests/modes/test_strict_mode.py b/tests/modes/test_strict_mode.py index 220410be..0e337cae 100644 --- a/tests/modes/test_strict_mode.py +++ b/tests/modes/test_strict_mode.py @@ -1,8 +1,10 @@ from textwrap import dedent +from pytest import Pytester -def test_strict_mode_cmdline(testdir): - testdir.makepyfile( + +def test_strict_mode_cmdline(pytester: Pytester): + pytester.makepyfile( dedent( """\ import asyncio @@ -16,12 +18,12 @@ async def test_a(): """ ) ) - result = testdir.runpytest("--asyncio-mode=strict") + result = pytester.runpytest("--asyncio-mode=strict") result.assert_outcomes(passed=1) -def test_strict_mode_cfg(testdir): - testdir.makepyfile( +def test_strict_mode_cfg(pytester: Pytester): + pytester.makepyfile( dedent( """\ import asyncio @@ -35,13 +37,13 @@ async def test_a(): """ ) ) - testdir.makefile(".ini", pytest="[pytest]\nasyncio_mode = strict\n") - result = testdir.runpytest() + pytester.makefile(".ini", pytest="[pytest]\nasyncio_mode = strict\n") + result = pytester.runpytest() result.assert_outcomes(passed=1) -def test_strict_mode_method_fixture(testdir): - testdir.makepyfile( +def test_strict_mode_method_fixture(pytester: Pytester): + pytester.makepyfile( dedent( """\ import asyncio @@ -64,12 +66,12 @@ async def test_a(self, fixture_a): """ ) ) - result = testdir.runpytest("--asyncio-mode=auto") + result = pytester.runpytest("--asyncio-mode=auto") result.assert_outcomes(passed=1) -def test_strict_mode_ignores_unmarked_coroutine(testdir): - testdir.makepyfile( +def test_strict_mode_ignores_unmarked_coroutine(pytester: Pytester): + pytester.makepyfile( dedent( """\ import pytest @@ -79,13 +81,13 @@ async def test_anything(): """ ) ) - result = testdir.runpytest_subprocess("--asyncio-mode=strict", "-W default") + result = pytester.runpytest_subprocess("--asyncio-mode=strict", "-W default") result.assert_outcomes(skipped=1, warnings=1) result.stdout.fnmatch_lines(["*async def functions are not natively supported*"]) -def test_strict_mode_ignores_unmarked_fixture(testdir): - testdir.makepyfile( +def test_strict_mode_ignores_unmarked_fixture(pytester: Pytester): + pytester.makepyfile( dedent( """\ import pytest @@ -100,7 +102,7 @@ async def test_anything(any_fixture): """ ) ) - result = testdir.runpytest_subprocess("--asyncio-mode=strict", "-W default") + result = pytester.runpytest_subprocess("--asyncio-mode=strict", "-W default") result.assert_outcomes(skipped=1, warnings=2) result.stdout.fnmatch_lines( [ From a6fb77f5f0d055c1e943d72fd70e793a983d8c20 Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Fri, 23 Aug 2024 13:17:56 +0200 Subject: [PATCH 065/226] refactor: Addressed warnings about missing default fixture loop scope in test_strict_mode. --- tests/modes/test_strict_mode.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/tests/modes/test_strict_mode.py b/tests/modes/test_strict_mode.py index 0e337cae..b8232d05 100644 --- a/tests/modes/test_strict_mode.py +++ b/tests/modes/test_strict_mode.py @@ -4,6 +4,7 @@ def test_strict_mode_cmdline(pytester: Pytester): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -23,6 +24,15 @@ async def test_a(): def test_strict_mode_cfg(pytester: Pytester): + pytester.makeini( + dedent( + """\ + [pytest] + asyncio_default_fixture_loop_scope = function + asyncio_mode = strict + """ + ) + ) pytester.makepyfile( dedent( """\ @@ -37,12 +47,12 @@ async def test_a(): """ ) ) - pytester.makefile(".ini", pytest="[pytest]\nasyncio_mode = strict\n") result = pytester.runpytest() result.assert_outcomes(passed=1) def test_strict_mode_method_fixture(pytester: Pytester): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -71,6 +81,7 @@ async def test_a(self, fixture_a): def test_strict_mode_ignores_unmarked_coroutine(pytester: Pytester): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -87,6 +98,7 @@ async def test_anything(): def test_strict_mode_ignores_unmarked_fixture(pytester: Pytester): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ From 466470ec22a9d3f1871552a2a7a8aebd503e70aa Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Fri, 23 Aug 2024 13:23:48 +0200 Subject: [PATCH 066/226] refactor: Addressed warnings about missing default fixture loop scope in tests/test_asyncio_fixture.py. --- tests/test_asyncio_fixture.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/test_asyncio_fixture.py b/tests/test_asyncio_fixture.py index 2577cba0..4bdabce2 100644 --- a/tests/test_asyncio_fixture.py +++ b/tests/test_asyncio_fixture.py @@ -2,6 +2,7 @@ from textwrap import dedent import pytest +from pytest import Pytester import pytest_asyncio @@ -43,8 +44,9 @@ async def test_fixture_with_params(fixture_with_params): @pytest.mark.parametrize("mode", ("auto", "strict")) -def test_sync_function_uses_async_fixture(testdir, mode): - testdir.makepyfile( +def test_sync_function_uses_async_fixture(pytester: Pytester, mode): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") + pytester.makepyfile( dedent( """\ import pytest_asyncio @@ -60,5 +62,5 @@ def test_sync_function_uses_async_fixture(always_true): """ ) ) - result = testdir.runpytest(f"--asyncio-mode={mode}") + result = pytester.runpytest(f"--asyncio-mode={mode}") result.assert_outcomes(passed=1) From 5db6f4f6710b5da3b3cb2060f5f26768899f2a04 Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Fri, 23 Aug 2024 13:26:47 +0200 Subject: [PATCH 067/226] refactor: Addressed warnings about missing default fixture loop scope in test_doctest. --- tests/test_doctest.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/test_doctest.py b/tests/test_doctest.py index 5b79619a..3795a4d7 100644 --- a/tests/test_doctest.py +++ b/tests/test_doctest.py @@ -4,6 +4,7 @@ def test_plugin_does_not_interfere_with_doctest_collection(pytester: Pytester): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( '''\ @@ -20,6 +21,7 @@ def any_function(): def test_plugin_does_not_interfere_with_doctest_textfile_collection(pytester: Pytester): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makefile(".txt", "") # collected as DoctestTextfile pytester.makepyfile( __init__="", From a5853d0d403a9b92fa40c57a9fe34c1ce5fdca1d Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Sat, 24 Aug 2024 21:57:32 +0200 Subject: [PATCH 068/226] refactor: Addressed warning about missing default fixture loop scope in tests/test_event_loop_fixture_finalizer.py. --- tests/test_event_loop_fixture_finalizer.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/test_event_loop_fixture_finalizer.py b/tests/test_event_loop_fixture_finalizer.py index ae260261..4306c33d 100644 --- a/tests/test_event_loop_fixture_finalizer.py +++ b/tests/test_event_loop_fixture_finalizer.py @@ -4,6 +4,7 @@ def test_event_loop_fixture_finalizer_returns_fresh_loop_after_test(pytester: Pytester): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -36,6 +37,7 @@ def test_2(): def test_event_loop_fixture_finalizer_handles_loop_set_to_none_sync( pytester: Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -53,6 +55,7 @@ def test_sync(event_loop): def test_event_loop_fixture_finalizer_handles_loop_set_to_none_async_without_fixture( pytester: Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -72,6 +75,7 @@ async def test_async_without_explicit_fixture_request(): def test_event_loop_fixture_finalizer_handles_loop_set_to_none_async_with_fixture( pytester: Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -94,6 +98,7 @@ async def test_async_with_explicit_fixture_request(event_loop): def test_event_loop_fixture_finalizer_raises_warning_when_fixture_leaves_loop_unclosed( pytester: Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -121,6 +126,7 @@ async def test_ends_with_unclosed_loop(): def test_event_loop_fixture_finalizer_raises_warning_when_test_leaves_loop_unclosed( pytester: Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ From 68a2da05f28bca33ecc5dd3427c3dbb3c6472f95 Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Sat, 24 Aug 2024 21:59:55 +0200 Subject: [PATCH 069/226] refactor: Addressed warnings about missing default fixture loop scope in tests/test_explicit_event_loop_fixture_request.py. --- tests/test_explicit_event_loop_fixture_request.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/test_explicit_event_loop_fixture_request.py b/tests/test_explicit_event_loop_fixture_request.py index e09893fa..382fbf7c 100644 --- a/tests/test_explicit_event_loop_fixture_request.py +++ b/tests/test_explicit_event_loop_fixture_request.py @@ -6,6 +6,7 @@ def test_emit_warning_when_event_loop_is_explicitly_requested_in_coroutine( pytester: Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -27,6 +28,7 @@ async def test_coroutine_emits_warning(event_loop): def test_emit_warning_when_event_loop_is_explicitly_requested_in_coroutine_method( pytester: Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -49,6 +51,7 @@ async def test_coroutine_emits_warning(self, event_loop): def test_emit_warning_when_event_loop_is_explicitly_requested_in_coroutine_staticmethod( pytester: Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -72,6 +75,7 @@ async def test_coroutine_emits_warning(event_loop): def test_emit_warning_when_event_loop_is_explicitly_requested_in_coroutine_fixture( pytester: Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -98,6 +102,7 @@ async def test_uses_fixture(emits_warning): def test_emit_warning_when_event_loop_is_explicitly_requested_in_async_gen_fixture( pytester: Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -124,6 +129,7 @@ async def test_uses_fixture(emits_warning): def test_does_not_emit_warning_when_event_loop_is_explicitly_requested_in_sync_function( pytester: Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -141,6 +147,7 @@ def test_uses_fixture(event_loop): def test_does_not_emit_warning_when_event_loop_is_explicitly_requested_in_sync_fixture( pytester: Pytester, ): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ From 9fa18ddd973d11ff43a65a23460c3eea20c6a244 Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Sat, 24 Aug 2024 22:01:36 +0200 Subject: [PATCH 070/226] refactor: Addressed warnings about missing default fixture loop scope in tests/test_import.py. --- tests/test_import.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/test_import.py b/tests/test_import.py index 9912ae0c..f1bf3caf 100644 --- a/tests/test_import.py +++ b/tests/test_import.py @@ -4,6 +4,7 @@ def test_import_warning_does_not_cause_internal_error(pytester: Pytester): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -19,6 +20,7 @@ async def test_errors_out(): def test_import_warning_in_package_does_not_cause_internal_error(pytester: Pytester): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( __init__=dedent( """\ @@ -37,6 +39,7 @@ async def test_errors_out(): def test_does_not_import_unrelated_packages(pytester: Pytester): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pkg_dir = pytester.mkpydir("mypkg") pkg_dir.joinpath("__init__.py").write_text( dedent( From 60af27b203af31c775791decbf3ec6fdfab1e846 Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Sat, 24 Aug 2024 22:05:25 +0200 Subject: [PATCH 071/226] refactor: Addressed warnigs about missing default fixture loop scope in tests/test_is_async_test.py, tests/test_simple.py, and tests/test_skips.py. --- tests/test_is_async_test.py | 4 ++++ tests/test_simple.py | 7 +++++-- tests/test_skips.py | 7 +++++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/tests/test_is_async_test.py b/tests/test_is_async_test.py index e0df54de..d69a54f6 100644 --- a/tests/test_is_async_test.py +++ b/tests/test_is_async_test.py @@ -4,6 +4,7 @@ def test_returns_false_for_sync_item(pytester: Pytester): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -28,6 +29,7 @@ def pytest_collection_modifyitems(items): def test_returns_true_for_marked_coroutine_item_in_strict_mode(pytester: Pytester): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -53,6 +55,7 @@ def pytest_collection_modifyitems(items): def test_returns_false_for_unmarked_coroutine_item_in_strict_mode(pytester: Pytester): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -77,6 +80,7 @@ def pytest_collection_modifyitems(items): def test_returns_true_for_unmarked_coroutine_item_in_auto_mode(pytester: Pytester): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ diff --git a/tests/test_simple.py b/tests/test_simple.py index f5f52a8d..c40a6809 100644 --- a/tests/test_simple.py +++ b/tests/test_simple.py @@ -26,6 +26,7 @@ async def test_asyncio_marker(): def test_asyncio_marker_compatibility_with_xfail(pytester: Pytester): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -45,6 +46,7 @@ async def test_asyncio_marker_fail(): def test_asyncio_auto_mode_compatibility_with_xfail(pytester: Pytester): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -101,8 +103,9 @@ async def test_event_loop_before_fixture(self, loop): assert await loop.run_in_executor(None, self.foo) == 1 -def test_invalid_asyncio_mode(testdir): - result = testdir.runpytest("-o", "asyncio_mode=True") +def test_invalid_asyncio_mode(pytester): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") + result = pytester.runpytest("-o", "asyncio_mode=True") result.stderr.no_fnmatch_line("INTERNALERROR> *") result.stderr.fnmatch_lines( "ERROR: 'True' is not a valid asyncio_mode. Valid modes: auto, strict." diff --git a/tests/test_skips.py b/tests/test_skips.py index 5d7aa303..96582ac0 100644 --- a/tests/test_skips.py +++ b/tests/test_skips.py @@ -4,6 +4,7 @@ def test_asyncio_strict_mode_skip(pytester: Pytester): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -22,6 +23,7 @@ async def test_no_warning_on_skip(): def test_asyncio_auto_mode_skip(pytester: Pytester): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -39,6 +41,7 @@ async def test_no_warning_on_skip(): def test_asyncio_strict_mode_module_level_skip(pytester: Pytester): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -57,6 +60,7 @@ async def test_is_skipped(): def test_asyncio_auto_mode_module_level_skip(pytester: Pytester): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -74,6 +78,7 @@ async def test_is_skipped(): def test_asyncio_auto_mode_wrong_skip_usage(pytester: Pytester): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -91,6 +96,7 @@ async def test_is_skipped(): def test_unittest_skiptest_compatibility(pytester: Pytester): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( dedent( """\ @@ -108,6 +114,7 @@ async def test_is_skipped(): def test_skip_in_module_does_not_skip_package(pytester: Pytester): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") pytester.makepyfile( __init__="", test_skip=dedent( From cf106746984664805fcff1a2f62cb421b2908560 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Aug 2024 18:31:42 +0000 Subject: [PATCH 072/226] Build(deps): Bump hypothesis in /dependencies/default Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.111.1 to 6.111.2. - [Release notes](https://github.com/HypothesisWorks/hypothesis/releases) - [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.111.1...hypothesis-python-6.111.2) --- updated-dependencies: - dependency-name: hypothesis dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index 1221d3b9..238b3810 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -1,7 +1,7 @@ attrs==24.2.0 coverage==7.6.1 exceptiongroup==1.2.2 -hypothesis==6.111.1 +hypothesis==6.111.2 iniconfig==2.0.0 packaging==24.1 pluggy==1.5.0 From b1dc0c3e2e82750bdc6dbdf668d519aaa89c036c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 6 Sep 2024 07:38:34 +0200 Subject: [PATCH 073/226] Build(deps): Bump pypa/gh-action-pypi-publish from 1.9.0 to 1.10.1 (#931) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Build(deps): Bump pypa/gh-action-pypi-publish from 1.9.0 to 1.10.0 Bumps [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) from 1.9.0 to 1.10.0. - [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases) - [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/v1.9.0...v1.10.0) --- updated-dependencies: - dependency-name: pypa/gh-action-pypi-publish dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * Opt into uploading PEP 740 digital publish attestations to PyPI https://github.com/pypa/gh-action-pypi-publish/pull/236 * Bump `pypa/gh-action-pypi-publish` 1.10.1 --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Sviatoslav Sydorenko (Святослав Сидоренко) --- .github/workflows/main.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a6851845..c4320503 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -149,8 +149,9 @@ jobs: run: | pandoc -s -o README.md README.rst - name: PyPI upload - uses: pypa/gh-action-pypi-publish@v1.9.0 + uses: pypa/gh-action-pypi-publish@v1.10.1 with: + attestations: true packages-dir: dist password: ${{ secrets.PYPI_API_TOKEN }} - name: GitHub Release From 28034142742be64a872e21e80cdb93fe792c9a07 Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Thu, 19 Sep 2024 07:02:29 +0200 Subject: [PATCH 074/226] build: Moved configuration of ommited files for coverage from Makefile to setup.cfg. --- Makefile | 2 +- setup.cfg | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index e1ef5d27..30642a1f 100644 --- a/Makefile +++ b/Makefile @@ -21,7 +21,7 @@ clean-test: ## remove test and coverage artifacts rm -fr htmlcov/ test: - coverage run --parallel-mode --omit */_version.py -m pytest + coverage run --parallel-mode -m pytest install: pip install -U pre-commit diff --git a/setup.cfg b/setup.cfg index 00c6bdd4..091b518a 100644 --- a/setup.cfg +++ b/setup.cfg @@ -58,6 +58,7 @@ pytest11 = [coverage:run] source = pytest_asyncio branch = true +omit = */_version.py [coverage:report] show_missing = true From 3d1402268bb197eac5d8cfa1c1d211f87af24e25 Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Thu, 19 Sep 2024 07:10:17 +0200 Subject: [PATCH 075/226] build: Move configuration of parallel mode for coverage from Makefile to setup.cfg. --- Makefile | 2 +- setup.cfg | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 30642a1f..fe816058 100644 --- a/Makefile +++ b/Makefile @@ -21,7 +21,7 @@ clean-test: ## remove test and coverage artifacts rm -fr htmlcov/ test: - coverage run --parallel-mode -m pytest + coverage run -m pytest install: pip install -U pre-commit diff --git a/setup.cfg b/setup.cfg index 091b518a..6d053045 100644 --- a/setup.cfg +++ b/setup.cfg @@ -59,6 +59,7 @@ pytest11 = source = pytest_asyncio branch = true omit = */_version.py +parallel = true [coverage:report] show_missing = true From c213690be3edce7e744e1efd546886cdead424cd Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Thu, 19 Sep 2024 07:14:39 +0200 Subject: [PATCH 076/226] ci: Fail pipeline when coverage data cannot be uploaded. If we simply emit a warning (the default), the pipeline will fail during the check step when trying to combine the coverage data. By changing this from warning to error, we fail the pipeline earlier and save time debugging issues. --- .github/workflows/main.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c4320503..3383694e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -89,6 +89,7 @@ jobs: with: name: coverage-python-${{ matrix.python-version }} path: .coverage.* + if-no-files-found: error check: name: Check From 32af83832c59904e5972d3e7c9efa8468ffc8dfc Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Thu, 19 Sep 2024 07:24:36 +0200 Subject: [PATCH 077/226] build: Write coverage files to the "coverage" subdirectory. Coverage writes coverage reports to ".coverage" by default. The GitHub action "upload-artifact" no longer includes hidden files by default. This patch changes the coverage file name to a non-hidden file path. --- .github/workflows/main.yml | 3 ++- .gitignore | 3 +-- Makefile | 2 +- setup.cfg | 1 + 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 3383694e..e8d2a210 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -88,7 +88,7 @@ jobs: if: "!endsWith(matrix.os, 'windows')" with: name: coverage-python-${{ matrix.python-version }} - path: .coverage.* + path: coverage/coverage.* if-no-files-found: error check: @@ -113,6 +113,7 @@ jobs: uses: actions/download-artifact@v4 with: pattern: coverage-* + path: coverage merge-multiple: true - name: Combine coverage data and create report run: | diff --git a/.gitignore b/.gitignore index 7dd9b771..5a568761 100644 --- a/.gitignore +++ b/.gitignore @@ -37,8 +37,7 @@ pip-delete-this-directory.txt # Unit test / coverage reports htmlcov/ .tox/ -.coverage -.coverage.* +coverage/ .pytest_cache nosetests.xml coverage.xml diff --git a/Makefile b/Makefile index fe816058..83c8ba81 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ clean-pyc: ## remove Python file artifacts clean-test: ## remove test and coverage artifacts rm -fr .tox/ - rm -f .coverage + rm -fr coverage/ rm -fr htmlcov/ test: diff --git a/setup.cfg b/setup.cfg index 6d053045..cd037b04 100644 --- a/setup.cfg +++ b/setup.cfg @@ -58,6 +58,7 @@ pytest11 = [coverage:run] source = pytest_asyncio branch = true +data_file = coverage/coverage omit = */_version.py parallel = true From ff81f2b44e81ee601c14eff87a4a0ea8b25ac4c2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 19 Sep 2024 07:57:56 +0000 Subject: [PATCH 078/226] Build(deps): Bump urllib3 from 2.2.2 to 2.2.3 in /dependencies/docs Bumps [urllib3](https://github.com/urllib3/urllib3) from 2.2.2 to 2.2.3. - [Release notes](https://github.com/urllib3/urllib3/releases) - [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst) - [Commits](https://github.com/urllib3/urllib3/compare/2.2.2...2.2.3) --- updated-dependencies: - dependency-name: urllib3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dependencies/docs/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/docs/constraints.txt b/dependencies/docs/constraints.txt index 6df3c716..c72b9e05 100644 --- a/dependencies/docs/constraints.txt +++ b/dependencies/docs/constraints.txt @@ -20,4 +20,4 @@ sphinxcontrib-jquery==4.1 sphinxcontrib-jsmath==1.0.1 sphinxcontrib-qthelp==2.0.0 sphinxcontrib-serializinghtml==2.0.0 -urllib3==2.2.2 +urllib3==2.2.3 From d1c52f2c03646a416a1e6c216bc6daf461d812b9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 19 Sep 2024 08:00:24 +0000 Subject: [PATCH 079/226] Build(deps): Bump idna from 3.7 to 3.10 in /dependencies/docs Bumps [idna](https://github.com/kjd/idna) from 3.7 to 3.10. - [Release notes](https://github.com/kjd/idna/releases) - [Changelog](https://github.com/kjd/idna/blob/master/HISTORY.rst) - [Commits](https://github.com/kjd/idna/compare/v3.7...v3.10) --- updated-dependencies: - dependency-name: idna dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- dependencies/docs/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/docs/constraints.txt b/dependencies/docs/constraints.txt index c72b9e05..c29ee6b0 100644 --- a/dependencies/docs/constraints.txt +++ b/dependencies/docs/constraints.txt @@ -3,7 +3,7 @@ Babel==2.16.0 certifi==2024.7.4 charset-normalizer==3.3.2 docutils==0.20.1 -idna==3.7 +idna==3.10 imagesize==1.4.1 Jinja2==3.1.4 MarkupSafe==2.1.5 From b8357b83181334c5e9c52078d8dd0a1d0a824d8f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 19 Sep 2024 08:03:16 +0000 Subject: [PATCH 080/226] Build(deps): Bump hypothesis in /dependencies/default Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.111.2 to 6.112.1. - [Release notes](https://github.com/HypothesisWorks/hypothesis/releases) - [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.111.2...hypothesis-python-6.112.1) --- updated-dependencies: - dependency-name: hypothesis dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index 238b3810..61c0b383 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -1,7 +1,7 @@ attrs==24.2.0 coverage==7.6.1 exceptiongroup==1.2.2 -hypothesis==6.111.2 +hypothesis==6.112.1 iniconfig==2.0.0 packaging==24.1 pluggy==1.5.0 From c5d014237ff53d023e658eff9cd05fabc0a0f063 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 19 Sep 2024 08:05:30 +0000 Subject: [PATCH 081/226] Build(deps): Bump pytest from 8.3.2 to 8.3.3 in /dependencies/default Bumps [pytest](https://github.com/pytest-dev/pytest) from 8.3.2 to 8.3.3. - [Release notes](https://github.com/pytest-dev/pytest/releases) - [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest/compare/8.3.2...8.3.3) --- updated-dependencies: - dependency-name: pytest dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index 61c0b383..880d9f97 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -5,7 +5,7 @@ hypothesis==6.112.1 iniconfig==2.0.0 packaging==24.1 pluggy==1.5.0 -pytest==8.3.2 +pytest==8.3.3 sortedcontainers==2.4.0 tomli==2.0.1 typing_extensions==4.12.2 From 2b7dbf1d5008df28b6c80b682a17922129204aa0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 19 Sep 2024 08:09:52 +0000 Subject: [PATCH 082/226] Build(deps): Bump certifi in /dependencies/docs Bumps [certifi](https://github.com/certifi/python-certifi) from 2024.7.4 to 2024.8.30. - [Commits](https://github.com/certifi/python-certifi/compare/2024.07.04...2024.08.30) --- updated-dependencies: - dependency-name: certifi dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- dependencies/docs/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/docs/constraints.txt b/dependencies/docs/constraints.txt index c29ee6b0..f5a38793 100644 --- a/dependencies/docs/constraints.txt +++ b/dependencies/docs/constraints.txt @@ -1,6 +1,6 @@ alabaster==0.7.16 Babel==2.16.0 -certifi==2024.7.4 +certifi==2024.8.30 charset-normalizer==3.3.2 docutils==0.20.1 idna==3.10 From aefe2f4a10fda77a1c7a5d7cd43d8a44d4dd8054 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 19 Sep 2024 08:12:48 +0000 Subject: [PATCH 083/226] Build(deps): Bump deadsnakes/action from 3.1.0 to 3.2.0 Bumps [deadsnakes/action](https://github.com/deadsnakes/action) from 3.1.0 to 3.2.0. - [Release notes](https://github.com/deadsnakes/action/releases) - [Commits](https://github.com/deadsnakes/action/compare/v3.1.0...v3.2.0) --- updated-dependencies: - dependency-name: deadsnakes/action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e8d2a210..15f83540 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -70,7 +70,7 @@ jobs: if: "!endsWith(matrix.python-version, '-dev')" with: python-version: ${{ matrix.python-version }} - - uses: deadsnakes/action@v3.1.0 + - uses: deadsnakes/action@v3.2.0 if: endsWith(matrix.python-version, '-dev') with: python-version: ${{ matrix.python-version }} From d0436985afa086a01544545ff6c38bd7383e25a9 Mon Sep 17 00:00:00 2001 From: Peter Bierma Date: Thu, 29 Aug 2024 16:20:04 -0400 Subject: [PATCH 084/226] Switch to `inspect.iscoroutinefunction` over `asyncio.iscoroutinefunction` --- pytest_asyncio/plugin.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pytest_asyncio/plugin.py b/pytest_asyncio/plugin.py index 178fcaa6..b2a8fef5 100644 --- a/pytest_asyncio/plugin.py +++ b/pytest_asyncio/plugin.py @@ -176,7 +176,7 @@ def _make_asyncio_fixture_function( def _is_coroutine_or_asyncgen(obj: Any) -> bool: - return asyncio.iscoroutinefunction(obj) or inspect.isasyncgenfunction(obj) + return inspect.iscoroutinefunction(obj) or inspect.isasyncgenfunction(obj) def _get_asyncio_mode(config: Config) -> Mode: @@ -447,7 +447,7 @@ class Coroutine(PytestAsyncioFunction): @staticmethod def _can_substitute(item: Function) -> bool: func = item.obj - return asyncio.iscoroutinefunction(func) + return inspect.iscoroutinefunction(func) def runtest(self) -> None: self.obj = wrap_in_sync( @@ -512,7 +512,7 @@ def _can_substitute(item: Function) -> bool: return ( getattr(func, "is_hypothesis_test", False) # type: ignore[return-value] and getattr(func, "hypothesis", None) - and asyncio.iscoroutinefunction(func.hypothesis.inner_test) + and inspect.iscoroutinefunction(func.hypothesis.inner_test) ) def runtest(self) -> None: From 34411017b79b364c5ccac9cdd697477a23dae939 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 26 Aug 2024 22:47:27 +0000 Subject: [PATCH 085/226] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/mirrors-mypy: v1.11.1 → v1.11.2](https://github.com/pre-commit/mirrors-mypy/compare/v1.11.1...v1.11.2) - [github.com/sirosen/check-jsonschema: 0.29.1 → 0.29.2](https://github.com/sirosen/check-jsonschema/compare/0.29.1...0.29.2) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2ad9e702..4e4778b9 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -37,7 +37,7 @@ repos: - id: check-yaml - id: debug-statements - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.11.1 + rev: v1.11.2 hooks: - id: mypy exclude: ^(docs|tests)/.* @@ -65,7 +65,7 @@ repos: - 'SC1004:' stages: [manual] - repo: https://github.com/sirosen/check-jsonschema - rev: 0.29.1 + rev: 0.29.2 hooks: - id: check-github-actions ci: From fcd6b334ae6aa0e8a3dd808efc4a49ad60c406fa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Sep 2024 18:24:43 +0000 Subject: [PATCH 086/226] Build(deps): Bump pypa/gh-action-pypi-publish from 1.10.1 to 1.10.2 Bumps [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) from 1.10.1 to 1.10.2. - [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases) - [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/v1.10.1...v1.10.2) --- updated-dependencies: - dependency-name: pypa/gh-action-pypi-publish dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 15f83540..13ab1e53 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -151,7 +151,7 @@ jobs: run: | pandoc -s -o README.md README.rst - name: PyPI upload - uses: pypa/gh-action-pypi-publish@v1.10.1 + uses: pypa/gh-action-pypi-publish@v1.10.2 with: attestations: true packages-dir: dist From 330b0a9261452a29f7299202e489b209d0c8a901 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 23 Sep 2024 22:42:12 +0000 Subject: [PATCH 087/226] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/rhysd/actionlint: v1.7.1 → v1.7.2](https://github.com/rhysd/actionlint/compare/v1.7.1...v1.7.2) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4e4778b9..e23dc9fd 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -53,7 +53,7 @@ repos: hooks: - id: python-use-type-annotations - repo: https://github.com/rhysd/actionlint - rev: v1.7.1 + rev: v1.7.2 hooks: - id: actionlint-docker args: From 23f800aa39f8e1f744aa6626e4880f963ba39558 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 30 Sep 2024 22:58:24 +0000 Subject: [PATCH 088/226] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/rhysd/actionlint: v1.7.2 → v1.7.3](https://github.com/rhysd/actionlint/compare/v1.7.2...v1.7.3) - [github.com/sirosen/check-jsonschema: 0.29.2 → 0.29.3](https://github.com/sirosen/check-jsonschema/compare/0.29.2...0.29.3) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e23dc9fd..32eb6fa6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -53,7 +53,7 @@ repos: hooks: - id: python-use-type-annotations - repo: https://github.com/rhysd/actionlint - rev: v1.7.2 + rev: v1.7.3 hooks: - id: actionlint-docker args: @@ -65,7 +65,7 @@ repos: - 'SC1004:' stages: [manual] - repo: https://github.com/sirosen/check-jsonschema - rev: 0.29.2 + rev: 0.29.3 hooks: - id: check-github-actions ci: From 9120aeafd1593a748d136a2717495cfed841ba78 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Sep 2024 18:33:30 +0000 Subject: [PATCH 089/226] Build(deps): Bump hypothesis in /dependencies/default Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.112.1 to 6.112.2. - [Release notes](https://github.com/HypothesisWorks/hypothesis/releases) - [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.112.1...hypothesis-python-6.112.2) --- updated-dependencies: - dependency-name: hypothesis dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index 880d9f97..589c48b2 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -1,7 +1,7 @@ attrs==24.2.0 coverage==7.6.1 exceptiongroup==1.2.2 -hypothesis==6.112.1 +hypothesis==6.112.2 iniconfig==2.0.0 packaging==24.1 pluggy==1.5.0 From a900d95984ac2a21f75ad5a64bc0102d6acee463 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 4 Oct 2024 18:47:14 +0000 Subject: [PATCH 090/226] Build(deps): Bump pypa/gh-action-pypi-publish from 1.10.2 to 1.10.3 Bumps [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) from 1.10.2 to 1.10.3. - [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases) - [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/v1.10.2...v1.10.3) --- updated-dependencies: - dependency-name: pypa/gh-action-pypi-publish dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 13ab1e53..d08cc8f3 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -151,7 +151,7 @@ jobs: run: | pandoc -s -o README.md README.rst - name: PyPI upload - uses: pypa/gh-action-pypi-publish@v1.10.2 + uses: pypa/gh-action-pypi-publish@v1.10.3 with: attestations: true packages-dir: dist From becf018ddf52e6ff8af3b045bd2db38e2223c526 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 8 Oct 2024 00:36:20 +0000 Subject: [PATCH 091/226] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/pre-commit-hooks: v4.6.0 → v5.0.0](https://github.com/pre-commit/pre-commit-hooks/compare/v4.6.0...v5.0.0) - [github.com/pre-commit/pre-commit-hooks: v4.6.0 → v5.0.0](https://github.com/pre-commit/pre-commit-hooks/compare/v4.6.0...v5.0.0) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 32eb6fa6..3f17e792 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,7 +1,7 @@ --- repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.6.0 + rev: v5.0.0 hooks: - id: check-merge-conflict exclude: rst$ @@ -25,7 +25,7 @@ repos: - id: yamlfmt args: [--mapping, '2', --sequence, '2', --offset, '0'] - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.6.0 + rev: v5.0.0 hooks: - id: trailing-whitespace - id: end-of-file-fixer From 1b661b306ded9526caee5b469767c063dc377722 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Oct 2024 18:52:07 +0000 Subject: [PATCH 092/226] Build(deps): Bump tomli from 2.0.1 to 2.0.2 in /dependencies/default Bumps [tomli](https://github.com/hukkin/tomli) from 2.0.1 to 2.0.2. - [Changelog](https://github.com/hukkin/tomli/blob/master/CHANGELOG.md) - [Commits](https://github.com/hukkin/tomli/compare/2.0.1...2.0.2) --- updated-dependencies: - dependency-name: tomli dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index 589c48b2..42cb5823 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -7,5 +7,5 @@ packaging==24.1 pluggy==1.5.0 pytest==8.3.3 sortedcontainers==2.4.0 -tomli==2.0.1 +tomli==2.0.2 typing_extensions==4.12.2 From d7e8abd9f70bcf1fe2498c800b4d6acf8386a95e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Oct 2024 18:52:05 +0000 Subject: [PATCH 093/226] Build(deps): Bump hypothesis in /dependencies/default Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.112.2 to 6.112.4. - [Release notes](https://github.com/HypothesisWorks/hypothesis/releases) - [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.112.2...hypothesis-python-6.112.4) --- updated-dependencies: - dependency-name: hypothesis dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index 42cb5823..f9d30444 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -1,7 +1,7 @@ attrs==24.2.0 coverage==7.6.1 exceptiongroup==1.2.2 -hypothesis==6.112.2 +hypothesis==6.112.4 iniconfig==2.0.0 packaging==24.1 pluggy==1.5.0 From f460973d87ba0e03b215ab3290ed14ead30b73f9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Oct 2024 18:33:24 +0000 Subject: [PATCH 094/226] Build(deps): Bump sphinx-rtd-theme in /dependencies/docs Bumps [sphinx-rtd-theme](https://github.com/readthedocs/sphinx_rtd_theme) from 2.0.0 to 3.0.0. - [Changelog](https://github.com/readthedocs/sphinx_rtd_theme/blob/master/docs/changelog.rst) - [Commits](https://github.com/readthedocs/sphinx_rtd_theme/compare/2.0.0...3.0.0) --- updated-dependencies: - dependency-name: sphinx-rtd-theme dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- dependencies/docs/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/docs/constraints.txt b/dependencies/docs/constraints.txt index f5a38793..17d85c2d 100644 --- a/dependencies/docs/constraints.txt +++ b/dependencies/docs/constraints.txt @@ -12,7 +12,7 @@ Pygments==2.18.0 requests==2.32.3 snowballstemmer==2.2.0 Sphinx==7.4.7 -sphinx-rtd-theme==2.0.0 +sphinx-rtd-theme==3.0.0 sphinxcontrib-applehelp==2.0.0 sphinxcontrib-devhelp==2.0.0 sphinxcontrib-htmlhelp==2.1.0 From 08d0f896dd6fc82224759e950241c7588d4372e9 Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Tue, 8 Oct 2024 15:29:20 +0200 Subject: [PATCH 095/226] build: Bumped Sphinx to v8.0.2 --- dependencies/docs/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/docs/constraints.txt b/dependencies/docs/constraints.txt index 17d85c2d..2783d358 100644 --- a/dependencies/docs/constraints.txt +++ b/dependencies/docs/constraints.txt @@ -11,7 +11,7 @@ packaging==24.1 Pygments==2.18.0 requests==2.32.3 snowballstemmer==2.2.0 -Sphinx==7.4.7 +Sphinx==8.0.2 sphinx-rtd-theme==3.0.0 sphinxcontrib-applehelp==2.0.0 sphinxcontrib-devhelp==2.0.0 From 77e06c42439ca2ae85587eaf265ee85dc63a9387 Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Tue, 8 Oct 2024 15:33:39 +0200 Subject: [PATCH 096/226] build: Bumped docutils to v0.21.2 --- dependencies/docs/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/docs/constraints.txt b/dependencies/docs/constraints.txt index 2783d358..007b32cb 100644 --- a/dependencies/docs/constraints.txt +++ b/dependencies/docs/constraints.txt @@ -2,7 +2,7 @@ alabaster==0.7.16 Babel==2.16.0 certifi==2024.8.30 charset-normalizer==3.3.2 -docutils==0.20.1 +docutils==0.21.2 idna==3.10 imagesize==1.4.1 Jinja2==3.1.4 From 2d118d27e5111afaad2dc82d84d9e46093ed4d8e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Oct 2024 18:30:35 +0000 Subject: [PATCH 097/226] Build(deps): Bump sphinx-rtd-theme in /dependencies/docs Bumps [sphinx-rtd-theme](https://github.com/readthedocs/sphinx_rtd_theme) from 3.0.0 to 3.0.1. - [Changelog](https://github.com/readthedocs/sphinx_rtd_theme/blob/master/docs/changelog.rst) - [Commits](https://github.com/readthedocs/sphinx_rtd_theme/compare/3.0.0...3.0.1) --- updated-dependencies: - dependency-name: sphinx-rtd-theme dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dependencies/docs/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/docs/constraints.txt b/dependencies/docs/constraints.txt index 007b32cb..1e3a4877 100644 --- a/dependencies/docs/constraints.txt +++ b/dependencies/docs/constraints.txt @@ -12,7 +12,7 @@ Pygments==2.18.0 requests==2.32.3 snowballstemmer==2.2.0 Sphinx==8.0.2 -sphinx-rtd-theme==3.0.0 +sphinx-rtd-theme==3.0.1 sphinxcontrib-applehelp==2.0.0 sphinxcontrib-devhelp==2.0.0 sphinxcontrib-htmlhelp==2.1.0 From 19df5578711b506da4c8caa27f10aeec035ad7d6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Oct 2024 18:30:32 +0000 Subject: [PATCH 098/226] Build(deps): Bump markupsafe from 2.1.5 to 3.0.1 in /dependencies/docs Bumps [markupsafe](https://github.com/pallets/markupsafe) from 2.1.5 to 3.0.1. - [Release notes](https://github.com/pallets/markupsafe/releases) - [Changelog](https://github.com/pallets/markupsafe/blob/main/CHANGES.rst) - [Commits](https://github.com/pallets/markupsafe/compare/2.1.5...3.0.1) --- updated-dependencies: - dependency-name: markupsafe dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- dependencies/docs/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/docs/constraints.txt b/dependencies/docs/constraints.txt index 1e3a4877..c3adaaaa 100644 --- a/dependencies/docs/constraints.txt +++ b/dependencies/docs/constraints.txt @@ -6,7 +6,7 @@ docutils==0.21.2 idna==3.10 imagesize==1.4.1 Jinja2==3.1.4 -MarkupSafe==2.1.5 +MarkupSafe==3.0.1 packaging==24.1 Pygments==2.18.0 requests==2.32.3 From d69a19f2fa927efd9f16d623f3bfc149f7198033 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Oct 2024 18:30:28 +0000 Subject: [PATCH 099/226] Build(deps): Bump charset-normalizer in /dependencies/docs Bumps [charset-normalizer](https://github.com/Ousret/charset_normalizer) from 3.3.2 to 3.4.0. - [Release notes](https://github.com/Ousret/charset_normalizer/releases) - [Changelog](https://github.com/jawah/charset_normalizer/blob/master/CHANGELOG.md) - [Commits](https://github.com/Ousret/charset_normalizer/compare/3.3.2...3.4.0) --- updated-dependencies: - dependency-name: charset-normalizer dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- dependencies/docs/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/docs/constraints.txt b/dependencies/docs/constraints.txt index c3adaaaa..7a9dff5a 100644 --- a/dependencies/docs/constraints.txt +++ b/dependencies/docs/constraints.txt @@ -1,7 +1,7 @@ alabaster==0.7.16 Babel==2.16.0 certifi==2024.8.30 -charset-normalizer==3.3.2 +charset-normalizer==3.4.0 docutils==0.21.2 idna==3.10 imagesize==1.4.1 From 90ce06a43d821f153a1d2adb22c395eaf8542ce6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 21 Oct 2024 18:34:40 +0000 Subject: [PATCH 100/226] Build(deps): Bump markupsafe from 3.0.1 to 3.0.2 in /dependencies/docs Bumps [markupsafe](https://github.com/pallets/markupsafe) from 3.0.1 to 3.0.2. - [Release notes](https://github.com/pallets/markupsafe/releases) - [Changelog](https://github.com/pallets/markupsafe/blob/main/CHANGES.rst) - [Commits](https://github.com/pallets/markupsafe/compare/3.0.1...3.0.2) --- updated-dependencies: - dependency-name: markupsafe dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dependencies/docs/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/docs/constraints.txt b/dependencies/docs/constraints.txt index 7a9dff5a..b7be8005 100644 --- a/dependencies/docs/constraints.txt +++ b/dependencies/docs/constraints.txt @@ -6,7 +6,7 @@ docutils==0.21.2 idna==3.10 imagesize==1.4.1 Jinja2==3.1.4 -MarkupSafe==3.0.1 +MarkupSafe==3.0.2 packaging==24.1 Pygments==2.18.0 requests==2.32.3 From a3b0b9ade06e3772012e09926e60a01f7268dca8 Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Wed, 23 Oct 2024 18:48:14 +0200 Subject: [PATCH 101/226] ci: Stop testing with Python3.8. --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d08cc8f3..2b4cb161 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -62,7 +62,7 @@ jobs: strategy: matrix: os: [ubuntu, windows] - python-version: ['3.8', '3.9', '3.10', '3.11', '3.12', 3.13.0-beta.3] + python-version: ['3.9', '3.10', '3.11', '3.12', 3.13.0-beta.3] steps: - uses: actions/checkout@v4 From 49dad21538912c972d89b3f79306a64011cac37c Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Wed, 23 Oct 2024 18:51:08 +0200 Subject: [PATCH 102/226] test: Test pytest-min environmen with Python 3.9. --- tox.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tox.ini b/tox.ini index 79e96fa6..f0053788 100644 --- a/tox.ini +++ b/tox.ini @@ -71,8 +71,8 @@ skip_install = false [gh-actions] python = - 3.8: py38, pytest-min - 3.9: py39 + 3.8: py38 + 3.9: py39, pytest-min 3.10: py310 3.11: py311 3.12: py312 From b66a5904fa1d5ffbed999917391e0a153d244075 Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Wed, 23 Oct 2024 18:52:35 +0200 Subject: [PATCH 103/226] build: Remove Python 3.8 from tox configuration. --- tox.ini | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tox.ini b/tox.ini index f0053788..bdf37f77 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,6 @@ [tox] minversion = 3.14.0 -envlist = py38, py39, py310, py311, py312, py13, pytest-min, docs +envlist = py39, py310, py311, py312, py13, pytest-min, docs isolated_build = true passenv = CI @@ -71,7 +71,6 @@ skip_install = false [gh-actions] python = - 3.8: py38 3.9: py39, pytest-min 3.10: py310 3.11: py311 From 07b19a91f9a24169b85aa32d4059ec20237d6166 Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Wed, 23 Oct 2024 18:53:48 +0200 Subject: [PATCH 104/226] build: Bump minimum Python version to v3.9 --- setup.cfg | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/setup.cfg b/setup.cfg index cd037b04..3ae1ed28 100644 --- a/setup.cfg +++ b/setup.cfg @@ -21,7 +21,6 @@ classifiers = License :: OSI Approved :: Apache Software License - Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.10 Programming Language :: Python :: 3.11 @@ -35,7 +34,7 @@ classifiers = Typing :: Typed [options] -python_requires = >=3.8 +python_requires = >=3.9 packages = pytest_asyncio include_package_data = True From 4a08909358aeef544c7468aa59b52746723debb4 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Thu, 24 Oct 2024 08:36:52 +0200 Subject: [PATCH 105/226] Add pyproject-fmt --- .pre-commit-config.yaml | 6 ++++++ pyproject.toml | 7 ++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3f17e792..fe56a084 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -68,6 +68,12 @@ repos: rev: 0.29.3 hooks: - id: check-github-actions +- repo: https://github.com/tox-dev/pyproject-fmt + rev: 2.3.1 + hooks: + - id: pyproject-fmt + # https://pyproject-fmt.readthedocs.io/en/latest/#calculating-max-supported-python-version + additional_dependencies: [tox>=4.9] ci: skip: - actionlint-docker diff --git a/pyproject.toml b/pyproject.toml index 81540a53..8c4d9ea4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,10 +1,11 @@ [build-system] +build-backend = "setuptools.build_meta" + requires = [ - "setuptools>=51.0", + "setuptools>=51", + "setuptools-scm[toml]>=6.2", "wheel>=0.36", - "setuptools_scm[toml]>=6.2" ] -build-backend = "setuptools.build_meta" [tool.setuptools_scm] write_to = "pytest_asyncio/_version.py" From dfc4121f7bb32c9e602902aca27fff1d90e68355 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Thu, 24 Oct 2024 08:45:08 +0200 Subject: [PATCH 106/226] [pre-commit] Replace flake8 by ruff --- .pre-commit-config.yaml | 10 +++++----- pyproject.toml | 8 ++++++++ setup.cfg | 3 --- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index fe56a084..bef06f2b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -5,6 +5,11 @@ repos: hooks: - id: check-merge-conflict exclude: rst$ +- repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.7.0 + hooks: + - id: ruff + args: [--fix] - repo: https://github.com/asottile/yesqa rev: v1.5.0 hooks: @@ -43,11 +48,6 @@ repos: exclude: ^(docs|tests)/.* additional_dependencies: - pytest -- repo: https://github.com/pycqa/flake8 - rev: 7.1.1 - hooks: - - id: flake8 - language_version: python3 - repo: https://github.com/pre-commit/pygrep-hooks rev: v1.10.0 hooks: diff --git a/pyproject.toml b/pyproject.toml index 8c4d9ea4..da02e5c0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,3 +9,11 @@ requires = [ [tool.setuptools_scm] write_to = "pytest_asyncio/_version.py" + +[tool.ruff] +line-length = 88 +lint.select = [ + "E", # pycodestyle + "F", # pyflakes + "W", # pycodestyle +] diff --git a/setup.cfg b/setup.cfg index 3ae1ed28..886b9d62 100644 --- a/setup.cfg +++ b/setup.cfg @@ -74,6 +74,3 @@ junit_family=xunit2 filterwarnings = error ignore:The event_loop fixture provided by pytest-asyncio has been redefined.*:DeprecationWarning - -[flake8] -max-line-length = 88 From 5d542f67682e8f4b2835a190714c9a8675bc56aa Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Thu, 24 Oct 2024 09:56:11 +0200 Subject: [PATCH 107/226] [tox] Upgrade minimal version of tox See https://github.com/pytest-dev/pytest-asyncio/pull/970/files\#r1814442641 --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index bdf37f77..d6e65df9 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -minversion = 3.14.0 +minversion = 4.9.0 envlist = py39, py310, py311, py312, py13, pytest-min, docs isolated_build = true passenv = From 1607df18ba999111250e0d9daf9dd8139a01eca8 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Thu, 24 Oct 2024 08:47:58 +0200 Subject: [PATCH 108/226] Migrate from setup.cfg to pyproject.toml --- pyproject.toml | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++ setup.cfg | 76 ----------------------------------------- 2 files changed, 91 insertions(+), 76 deletions(-) delete mode 100644 setup.cfg diff --git a/pyproject.toml b/pyproject.toml index da02e5c0..05f634d7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,6 +7,65 @@ requires = [ "wheel>=0.36", ] +[project] +name = "pytest-asyncio" +description = "Pytest support for asyncio" +readme.content-type = "text/x-rst" +readme.file = "README.rst" +license.text = "Apache 2.0" +authors = [ + { name = "Tin Tvrtković ", email = "tinchester@gmail.com" }, +] +requires-python = ">=3.9" +classifiers = [ + "Development Status :: 4 - Beta", + "Framework :: AsyncIO", + "Framework :: Pytest", + "Intended Audience :: Developers", + "License :: OSI Approved :: Apache Software License", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Topic :: Software Development :: Testing", + "Typing :: Typed", +] +dynamic = [ + "version", +] + +dependencies = [ + "pytest>=8.2,<9", +] +optional-dependencies.docs = [ + "sphinx>=5.3", + "sphinx-rtd-theme>=1", +] +optional-dependencies.testing = [ + "coverage>=6.2", + "hypothesis>=5.7.1", +] +urls."Bug Tracker" = "https://github.com/pytest-dev/pytest-asyncio/issues" +urls.Changelog = "https://pytest-asyncio.readthedocs.io/en/latest/reference/changelog.html" +urls.Documentation = "https://pytest-asyncio.readthedocs.io" +urls.Homepage = "https://github.com/pytest-dev/pytest-asyncio" +urls."Source Code" = "https://github.com/pytest-dev/pytest-asyncio" +entry-points.pytest11.asyncio = "pytest_asyncio.plugin" + +[tool.setuptools] +packages = [ + "pytest_asyncio", +] +include-package-data = true +license-files = [ + "LICENSE", +] + +[tool.setuptools.dynamic.version] +attr = "pytest_asyncio.__version__" + [tool.setuptools_scm] write_to = "pytest_asyncio/_version.py" @@ -17,3 +76,35 @@ lint.select = [ "F", # pyflakes "W", # pycodestyle ] + +[tool.pytest.ini_options] +python_files = [ + "test_*.py", + "*_example.py", +] +addopts = "-rsx --tb=short" +testpaths = [ + "docs", + "tests", +] +asyncio_mode = "auto" +asyncio_default_fixture_loop_scope = "function" +junit_family = "xunit2" +filterwarnings = [ + "error", + "ignore:The event_loop fixture provided by pytest-asyncio has been redefined.*:DeprecationWarning", +] + +[tool.coverage.run] +source = [ + "pytest_asyncio", +] +branch = true +data_file = "coverage/coverage" +omit = [ + "*/_version.py", +] +parallel = true + +[tool.coverage.report] +show_missing = true diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 886b9d62..00000000 --- a/setup.cfg +++ /dev/null @@ -1,76 +0,0 @@ -[metadata] -name = pytest-asyncio -version = attr: pytest_asyncio.__version__ -url = https://github.com/pytest-dev/pytest-asyncio -project_urls = - Documentation = https://pytest-asyncio.readthedocs.io - Changelog = https://pytest-asyncio.readthedocs.io/en/latest/reference/changelog.html - Source Code = https://github.com/pytest-dev/pytest-asyncio - Bug Tracker = https://github.com/pytest-dev/pytest-asyncio/issues -description = Pytest support for asyncio -long_description = file: README.rst -long_description_content_type = text/x-rst -author = Tin Tvrtković -author_email = tinchester@gmail.com -license = Apache 2.0 -license_files = LICENSE -classifiers = - Development Status :: 4 - Beta - - Intended Audience :: Developers - - License :: OSI Approved :: Apache Software License - - Programming Language :: Python :: 3.9 - Programming Language :: Python :: 3.10 - Programming Language :: Python :: 3.11 - Programming Language :: Python :: 3.12 - Programming Language :: Python :: 3.13 - - Topic :: Software Development :: Testing - - Framework :: AsyncIO - Framework :: Pytest - Typing :: Typed - -[options] -python_requires = >=3.9 -packages = pytest_asyncio -include_package_data = True - -# Always adjust requirements.txt and pytest-min-requirements.txt when changing runtime dependencies -install_requires = - pytest >= 8.2,<9 - -[options.extras_require] -testing = - coverage >= 6.2 - hypothesis >= 5.7.1 -docs = - sphinx >= 5.3 - sphinx-rtd-theme >= 1.0 - -[options.entry_points] -pytest11 = - asyncio = pytest_asyncio.plugin - -[coverage:run] -source = pytest_asyncio -branch = true -data_file = coverage/coverage -omit = */_version.py -parallel = true - -[coverage:report] -show_missing = true - -[tool:pytest] -python_files = test_*.py *_example.py -addopts = -rsx --tb=short -testpaths = docs tests -asyncio_mode = auto -asyncio_default_fixture_loop_scope = function -junit_family=xunit2 -filterwarnings = - error - ignore:The event_loop fixture provided by pytest-asyncio has been redefined.*:DeprecationWarning From 4eeea39232894292eb4d291d17a6a026d9423555 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Thu, 24 Oct 2024 11:55:18 +0200 Subject: [PATCH 109/226] Avoid setuptools bug by keeping a small part of the setup.cfg --- pyproject.toml | 3 --- setup.cfg | 18 ++++++++++++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) create mode 100644 setup.cfg diff --git a/pyproject.toml b/pyproject.toml index 05f634d7..24e7dc56 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -63,9 +63,6 @@ license-files = [ "LICENSE", ] -[tool.setuptools.dynamic.version] -attr = "pytest_asyncio.__version__" - [tool.setuptools_scm] write_to = "pytest_asyncio/_version.py" diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 00000000..f68f54b8 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,18 @@ +[metadata] +# Not everything is in in pyproject.toml because of this issue: +; Traceback (most recent call last): +; File "/tmp/build-env-rud8b5r6/lib/python3.12/site-packages/setuptools/config/expand.py", line 69, in __getattr__ +; return next( +; ^^^^^ +;StopIteration +; +;The above exception was the direct cause of the following exception: +; +;Traceback (most recent call last): +; File "/tmp/build-env-rud8b5r6/lib/python3.12/site-packages/setuptools/config/expand.py", line 183, in read_attr +; return getattr(StaticModule(module_name, spec), attr_name) +; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +; File "/tmp/build-env-rud8b5r6/lib/python3.12/site-packages/setuptools/config/expand.py", line 75, in __getattr__ +; raise AttributeError(f"{self.name} has no attribute {attr}") from e +;AttributeError: pytest_asyncio has no attribute __version__ +version = attr: pytest_asyncio.__version__ From 594f5d0c9f082397553cb4e633b36f9f527d6d03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Thu, 24 Oct 2024 18:12:08 +0200 Subject: [PATCH 110/226] Fix typo in tox.ini --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index d6e65df9..9a0cf93b 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,6 @@ [tox] minversion = 4.9.0 -envlist = py39, py310, py311, py312, py13, pytest-min, docs +envlist = py39, py310, py311, py312, py313, pytest-min, docs isolated_build = true passenv = CI From 0eb7c0a8a62ce5df07d0be115589b67fadcf9f06 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Thu, 24 Oct 2024 08:55:59 +0200 Subject: [PATCH 111/226] [ruff] Add checks including pyupgrade --- pyproject.toml | 12 +++++++++--- pytest_asyncio/__init__.py | 2 +- pytest_asyncio/plugin.py | 38 ++++++++++++++++++-------------------- 3 files changed, 28 insertions(+), 24 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 24e7dc56..4b622e09 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -69,9 +69,15 @@ write_to = "pytest_asyncio/_version.py" [tool.ruff] line-length = 88 lint.select = [ - "E", # pycodestyle - "F", # pyflakes - "W", # pycodestyle + "E", # pycodestyle + "F", # pyflakes + "PGH004", # pygrep-hooks - Use specific rule codes when using noqa + "PIE", # flake8-pie + "PYI", # flake8-pyi + "RUF", # ruff + "T100", # flake8-debugger + "UP", # pyupgrade + "W", # pycodestyle ] [tool.pytest.ini_options] diff --git a/pytest_asyncio/__init__.py b/pytest_asyncio/__init__.py index 08dca478..f059e965 100644 --- a/pytest_asyncio/__init__.py +++ b/pytest_asyncio/__init__.py @@ -1,6 +1,6 @@ """The main point for importing pytest-asyncio items.""" -from ._version import version as __version__ # noqa +from ._version import version as __version__ # noqa: F401 from .plugin import fixture, is_async_test __all__ = ("fixture", "is_async_test") diff --git a/pytest_asyncio/plugin.py b/pytest_asyncio/plugin.py index b2a8fef5..11bfc919 100644 --- a/pytest_asyncio/plugin.py +++ b/pytest_asyncio/plugin.py @@ -8,23 +8,21 @@ import socket import warnings from asyncio import AbstractEventLoopPolicy -from textwrap import dedent -from typing import ( - Any, +from collections.abc import ( AsyncIterator, Awaitable, - Callable, - Dict, Generator, Iterable, Iterator, - List, - Literal, Mapping, - Optional, Sequence, - Set, - Type, +) +from textwrap import dedent +from typing import ( + Any, + Callable, + Literal, + Optional, TypeVar, Union, overload, @@ -215,7 +213,7 @@ def pytest_configure(config: Config) -> None: @pytest.hookimpl(tryfirst=True) -def pytest_report_header(config: Config) -> List[str]: +def pytest_report_header(config: Config) -> list[str]: """Add asyncio config to pytest header.""" mode = _get_asyncio_mode(config) default_loop_scope = config.getini("asyncio_default_fixture_loop_scope") @@ -224,7 +222,7 @@ def pytest_report_header(config: Config) -> List[str]: def _preprocess_async_fixtures( collector: Collector, - processed_fixturedefs: Set[FixtureDef], + processed_fixturedefs: set[FixtureDef], ) -> None: config = collector.config default_loop_scope = config.getini("asyncio_default_fixture_loop_scope") @@ -279,10 +277,10 @@ def _synchronize_async_fixture(fixturedef: FixtureDef) -> None: def _add_kwargs( func: Callable[..., Any], - kwargs: Dict[str, Any], + kwargs: dict[str, Any], event_loop: asyncio.AbstractEventLoop, request: FixtureRequest, -) -> Dict[str, Any]: +) -> dict[str, Any]: sig = inspect.signature(func) ret = kwargs.copy() if "request" in sig.parameters: @@ -394,7 +392,7 @@ class PytestAsyncioFunction(Function): @classmethod def item_subclass_for( cls, item: Function, / - ) -> Union[Type["PytestAsyncioFunction"], None]: + ) -> Union[type["PytestAsyncioFunction"], None]: """ Returns a subclass of PytestAsyncioFunction if there is a specialized subclass for the specified function item. @@ -522,7 +520,7 @@ def runtest(self) -> None: super().runtest() -_HOLDER: Set[FixtureDef] = set() +_HOLDER: set[FixtureDef] = set() # The function name needs to start with "pytest_" @@ -531,7 +529,7 @@ def runtest(self) -> None: def pytest_pycollect_makeitem_preprocess_async_fixtures( collector: Union[pytest.Module, pytest.Class], name: str, obj: object ) -> Union[ - pytest.Item, pytest.Collector, List[Union[pytest.Item, pytest.Collector]], None + pytest.Item, pytest.Collector, list[Union[pytest.Item, pytest.Collector]], None ]: """A pytest hook to collect asyncio coroutines.""" if not collector.funcnamefilter(name): @@ -555,7 +553,7 @@ def pytest_pycollect_makeitem_convert_async_functions_to_subclass( node_or_list_of_nodes: Union[ pytest.Item, pytest.Collector, - List[Union[pytest.Item, pytest.Collector]], + list[Union[pytest.Item, pytest.Collector]], None, ] = hook_result.get_result() except BaseException as e: @@ -585,7 +583,7 @@ def pytest_pycollect_makeitem_convert_async_functions_to_subclass( _event_loop_fixture_id = StashKey[str]() -_fixture_scope_by_collector_type: Mapping[Type[pytest.Collector], _ScopeName] = { +_fixture_scope_by_collector_type: Mapping[type[pytest.Collector], _ScopeName] = { Class: "class", # Package is a subclass of module and the dict is used in isinstance checks # Therefore, the order matters and Package needs to appear before Module @@ -596,7 +594,7 @@ def pytest_pycollect_makeitem_convert_async_functions_to_subclass( # A stack used to push package-scoped loops during collection of a package # and pop those loops during collection of a Module -__package_loop_stack: List[Union[FixtureFunctionMarker, FixtureFunction]] = [] +__package_loop_stack: list[Union[FixtureFunctionMarker, FixtureFunction]] = [] @pytest.hookimpl From 60528d507726053311973e6d4724d8879cb77874 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Thu, 24 Oct 2024 09:06:08 +0200 Subject: [PATCH 112/226] [ruff] Add bugbears check --- pyproject.toml | 5 +++++ pytest_asyncio/plugin.py | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 4b622e09..25930f18 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -69,6 +69,7 @@ write_to = "pytest_asyncio/_version.py" [tool.ruff] line-length = 88 lint.select = [ + "B", # bugbear "E", # pycodestyle "F", # pyflakes "PGH004", # pygrep-hooks - Use specific rule codes when using noqa @@ -79,6 +80,10 @@ lint.select = [ "UP", # pyupgrade "W", # pycodestyle ] +lint.ignore = [ + # bugbear ignore + "B028", # No explicit `stacklevel` keyword argument found +] [tool.pytest.ini_options] python_files = [ diff --git a/pytest_asyncio/plugin.py b/pytest_asyncio/plugin.py index 11bfc919..c7dfb5c4 100644 --- a/pytest_asyncio/plugin.py +++ b/pytest_asyncio/plugin.py @@ -183,11 +183,11 @@ def _get_asyncio_mode(config: Config) -> Mode: val = config.getini("asyncio_mode") try: return Mode(val) - except ValueError: + except ValueError as e: modes = ", ".join(m.value for m in Mode) raise pytest.UsageError( f"{val!r} is not a valid asyncio_mode. Valid modes: {modes}." - ) + ) from e _DEFAULT_FIXTURE_LOOP_SCOPE_UNSET = """\ From 58bac5970ae0c1a80bb7ba9713a90871da2a8a00 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Thu, 24 Oct 2024 09:08:53 +0200 Subject: [PATCH 113/226] [ruff] Add pydocstyle check (mostly autofix) --- pyproject.toml | 21 +++++++++++++++++++++ pytest_asyncio/plugin.py | 11 +++++------ tests/hypothesis/test_base.py | 3 ++- tests/test_simple.py | 6 ++++-- 4 files changed, 32 insertions(+), 9 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 25930f18..f97c890f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -68,8 +68,10 @@ write_to = "pytest_asyncio/_version.py" [tool.ruff] line-length = 88 +format.docstring-code-format = true lint.select = [ "B", # bugbear + "D", # pydocstyle "E", # pycodestyle "F", # pyflakes "PGH004", # pygrep-hooks - Use specific rule codes when using noqa @@ -80,9 +82,28 @@ lint.select = [ "UP", # pyupgrade "W", # pycodestyle ] + lint.ignore = [ # bugbear ignore "B028", # No explicit `stacklevel` keyword argument found + # pydocstyle ignore + "D100", # Missing docstring in public module + "D101", # Missing docstring in public class + "D102", # Missing docstring in public method + "D103", # Missing docstring in public function + "D104", # Missing docstring in public package + "D105", # Missing docstring in magic method + "D106", # Missing docstring in public nested class + "D107", # Missing docstring in `__init__` + "D203", # `one-blank-line-before-class` (D203) and `no-blank-line-before-class` (D211) are incompatible + "D205", # 1 blank line required between summary line and description + "D209", # [*] Multi-line docstring closing quotes should be on a separate line + "D212", # `multi-line-summary-first-line` (D212) and `multi-line-summary-second-line` (D213) are incompatible. + "D400", # First line should end with a period + "D401", # First line of docstring should be in imperative mood + "D402", # First line should not be the function's signature + "D404", # First word of the docstring should not be "This" + "D415", # First line should end with a period, question mark, or exclamation point ] [tool.pytest.ini_options] diff --git a/pytest_asyncio/plugin.py b/pytest_asyncio/plugin.py index c7dfb5c4..7439068c 100644 --- a/pytest_asyncio/plugin.py +++ b/pytest_asyncio/plugin.py @@ -266,9 +266,7 @@ def _preprocess_async_fixtures( def _synchronize_async_fixture(fixturedef: FixtureDef) -> None: - """ - Wraps the fixture function of an async fixture in a synchronous function. - """ + """Wraps the fixture function of an async fixture in a synchronous function.""" if inspect.isasyncgenfunction(fixturedef.func): _wrap_asyncgen_fixture(fixturedef) elif inspect.iscoroutinefunction(fixturedef.func): @@ -908,9 +906,10 @@ def pytest_pyfunc_call(pyfuncitem: Function) -> Optional[object]: def wrap_in_sync( func: Callable[..., Awaitable[Any]], ): - """Return a sync wrapper around an async function executing it in the - current event loop.""" - + """ + Return a sync wrapper around an async function executing it in the + current event loop. + """ # if the function is already wrapped, we rewrap using the original one # not using __wrapped__ because the original function may already be # a wrapped one diff --git a/tests/hypothesis/test_base.py b/tests/hypothesis/test_base.py index 176c9aee..ee87a724 100644 --- a/tests/hypothesis/test_base.py +++ b/tests/hypothesis/test_base.py @@ -1,4 +1,5 @@ -"""Tests for the Hypothesis integration, which wraps async functions in a +""" +Tests for the Hypothesis integration, which wraps async functions in a sync shim for Hypothesis. """ diff --git a/tests/test_simple.py b/tests/test_simple.py index c40a6809..c39dfda8 100644 --- a/tests/test_simple.py +++ b/tests/test_simple.py @@ -75,8 +75,10 @@ class TestMarkerInClassBasedTests: @pytest.mark.asyncio async def test_asyncio_marker_with_implicit_loop_fixture(self): - """Test the "asyncio" marker works on a method in - a class-based test with implicit loop fixture.""" + """ + Test the "asyncio" marker works on a method in + a class-based test with implicit loop fixture. + """ ret = await async_coro() assert ret == "ok" From 720e28c17b65d706aac7890c5ed34e6c60d2c84e Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Thu, 24 Oct 2024 09:21:39 +0200 Subject: [PATCH 114/226] [typing.Union -> |] Add 'from __future__ import annotations' everywhere --- pyproject.toml | 2 + pytest_asyncio/__init__.py | 2 + pytest_asyncio/plugin.py | 80 +++++++++---------- tests/async_fixtures/test_async_fixtures.py | 2 + .../test_async_fixtures_scope.py | 2 + .../test_async_fixtures_with_finalizer.py | 2 + .../async_fixtures/test_async_gen_fixtures.py | 2 + tests/async_fixtures/test_nested.py | 2 + .../async_fixtures/test_parametrized_loop.py | 2 + .../test_shared_module_fixture.py | 2 + tests/conftest.py | 2 + tests/hypothesis/test_base.py | 2 + tests/loop_fixture_scope/conftest.py | 2 + .../test_loop_fixture_scope.py | 2 + tests/markers/test_class_scope.py | 2 + tests/markers/test_function_scope.py | 2 + tests/markers/test_invalid_arguments.py | 2 + tests/markers/test_module_scope.py | 2 + tests/markers/test_package_scope.py | 2 + tests/markers/test_session_scope.py | 2 + tests/modes/test_auto_mode.py | 2 + tests/modes/test_strict_mode.py | 2 + tests/test_asyncio_fixture.py | 2 + tests/test_asyncio_mark.py | 2 + tests/test_dependent_fixtures.py | 2 + tests/test_doctest.py | 2 + tests/test_event_loop_fixture.py | 2 + tests/test_event_loop_fixture_finalizer.py | 2 + ...event_loop_fixture_override_deprecation.py | 2 + ...est_explicit_event_loop_fixture_request.py | 2 + tests/test_fixture_loop_scopes.py | 2 + tests/test_import.py | 2 + tests/test_is_async_test.py | 2 + tests/test_multiloop.py | 2 + tests/test_port_factories.py | 2 + tests/test_simple.py | 2 + tests/test_skips.py | 2 + tests/test_subprocess.py | 2 + tools/get-version.py | 2 + 39 files changed, 112 insertions(+), 44 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index f97c890f..b89c24da 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -74,8 +74,10 @@ lint.select = [ "D", # pydocstyle "E", # pycodestyle "F", # pyflakes + "FA100", # add future annotations "PGH004", # pygrep-hooks - Use specific rule codes when using noqa "PIE", # flake8-pie + "PLE", # pylint error "PYI", # flake8-pyi "RUF", # ruff "T100", # flake8-debugger diff --git a/pytest_asyncio/__init__.py b/pytest_asyncio/__init__.py index f059e965..c25c1bf1 100644 --- a/pytest_asyncio/__init__.py +++ b/pytest_asyncio/__init__.py @@ -1,5 +1,7 @@ """The main point for importing pytest-asyncio items.""" +from __future__ import annotations + from ._version import version as __version__ # noqa: F401 from .plugin import fixture, is_async_test diff --git a/pytest_asyncio/plugin.py b/pytest_asyncio/plugin.py index 7439068c..1c81fee5 100644 --- a/pytest_asyncio/plugin.py +++ b/pytest_asyncio/plugin.py @@ -1,5 +1,7 @@ """pytest-asyncio implementation.""" +from __future__ import annotations + import asyncio import contextlib import enum @@ -22,7 +24,6 @@ Any, Callable, Literal, - Optional, TypeVar, Union, overload, @@ -110,16 +111,16 @@ def pytest_addoption(parser: Parser, pluginmanager: PytestPluginManager) -> None def fixture( fixture_function: FixtureFunction, *, - scope: "Union[_ScopeName, Callable[[str, Config], _ScopeName]]" = ..., - loop_scope: Union[_ScopeName, None] = ..., - params: Optional[Iterable[object]] = ..., + scope: _ScopeName | Callable[[str, Config], _ScopeName] = ..., + loop_scope: _ScopeName | None = ..., + params: Iterable[object] | None = ..., autouse: bool = ..., - ids: Union[ - Iterable[Union[str, float, int, bool, None]], - Callable[[Any], Optional[object]], - None, - ] = ..., - name: Optional[str] = ..., + ids: ( + Iterable[str | float | int | bool | None] + | Callable[[Any], object | None] + | None + ) = ..., + name: str | None = ..., ) -> FixtureFunction: ... @@ -127,24 +128,24 @@ def fixture( def fixture( fixture_function: None = ..., *, - scope: "Union[_ScopeName, Callable[[str, Config], _ScopeName]]" = ..., - loop_scope: Union[_ScopeName, None] = ..., - params: Optional[Iterable[object]] = ..., + scope: _ScopeName | Callable[[str, Config], _ScopeName] = ..., + loop_scope: _ScopeName | None = ..., + params: Iterable[object] | None = ..., autouse: bool = ..., - ids: Union[ - Iterable[Union[str, float, int, bool, None]], - Callable[[Any], Optional[object]], - None, - ] = ..., - name: Optional[str] = None, + ids: ( + Iterable[str | float | int | bool | None] + | Callable[[Any], object | None] + | None + ) = ..., + name: str | None = None, ) -> FixtureFunctionMarker: ... def fixture( - fixture_function: Optional[FixtureFunction] = None, - loop_scope: Union[_ScopeName, None] = None, + fixture_function: FixtureFunction | None = None, + loop_scope: _ScopeName | None = None, **kwargs: Any, -) -> Union[FixtureFunction, FixtureFunctionMarker]: +) -> FixtureFunction | FixtureFunctionMarker: if fixture_function is not None: _make_asyncio_fixture_function(fixture_function, loop_scope) return pytest.fixture(fixture_function, **kwargs) @@ -163,9 +164,7 @@ def _is_asyncio_fixture_function(obj: Any) -> bool: return getattr(obj, "_force_asyncio_fixture", False) -def _make_asyncio_fixture_function( - obj: Any, loop_scope: Union[_ScopeName, None] -) -> None: +def _make_asyncio_fixture_function(obj: Any, loop_scope: _ScopeName | None) -> None: if hasattr(obj, "__func__"): # instance method, check the function object obj = obj.__func__ @@ -288,7 +287,7 @@ def _add_kwargs( return ret -def _perhaps_rebind_fixture_func(func: _T, instance: Optional[Any]) -> _T: +def _perhaps_rebind_fixture_func(func: _T, instance: Any | None) -> _T: if instance is not None: # The fixture needs to be bound to the actual request.instance # so it is bound to the same object as the test method. @@ -388,9 +387,7 @@ class PytestAsyncioFunction(Function): """Base class for all test functions managed by pytest-asyncio.""" @classmethod - def item_subclass_for( - cls, item: Function, / - ) -> Union[type["PytestAsyncioFunction"], None]: + def item_subclass_for(cls, item: Function, /) -> type[PytestAsyncioFunction] | None: """ Returns a subclass of PytestAsyncioFunction if there is a specialized subclass for the specified function item. @@ -525,10 +522,8 @@ def runtest(self) -> None: # see https://github.com/pytest-dev/pytest/issues/11307 @pytest.hookimpl(specname="pytest_pycollect_makeitem", tryfirst=True) def pytest_pycollect_makeitem_preprocess_async_fixtures( - collector: Union[pytest.Module, pytest.Class], name: str, obj: object -) -> Union[ - pytest.Item, pytest.Collector, list[Union[pytest.Item, pytest.Collector]], None -]: + collector: pytest.Module | pytest.Class, name: str, obj: object +) -> pytest.Item | pytest.Collector | list[pytest.Item | pytest.Collector] | None: """A pytest hook to collect asyncio coroutines.""" if not collector.funcnamefilter(name): return None @@ -540,7 +535,7 @@ def pytest_pycollect_makeitem_preprocess_async_fixtures( # see https://github.com/pytest-dev/pytest/issues/11307 @pytest.hookimpl(specname="pytest_pycollect_makeitem", hookwrapper=True) def pytest_pycollect_makeitem_convert_async_functions_to_subclass( - collector: Union[pytest.Module, pytest.Class], name: str, obj: object + collector: pytest.Module | pytest.Class, name: str, obj: object ) -> Generator[None, pluggy.Result, None]: """ Converts coroutines and async generators collected as pytest.Functions @@ -548,12 +543,9 @@ def pytest_pycollect_makeitem_convert_async_functions_to_subclass( """ hook_result = yield try: - node_or_list_of_nodes: Union[ - pytest.Item, - pytest.Collector, - list[Union[pytest.Item, pytest.Collector]], - None, - ] = hook_result.get_result() + node_or_list_of_nodes: ( + pytest.Item | pytest.Collector | list[pytest.Item | pytest.Collector] | None + ) = hook_result.get_result() except BaseException as e: hook_result.force_exception(e) return @@ -592,7 +584,7 @@ def pytest_pycollect_makeitem_convert_async_functions_to_subclass( # A stack used to push package-scoped loops during collection of a package # and pop those loops during collection of a Module -__package_loop_stack: list[Union[FixtureFunctionMarker, FixtureFunction]] = [] +__package_loop_stack: list[FixtureFunctionMarker | FixtureFunction] = [] @pytest.hookimpl @@ -868,7 +860,7 @@ def _provide_clean_event_loop() -> None: def _get_event_loop_no_warn( - policy: Optional[AbstractEventLoopPolicy] = None, + policy: AbstractEventLoopPolicy | None = None, ) -> asyncio.AbstractEventLoop: with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) @@ -879,7 +871,7 @@ def _get_event_loop_no_warn( @pytest.hookimpl(tryfirst=True, hookwrapper=True) -def pytest_pyfunc_call(pyfuncitem: Function) -> Optional[object]: +def pytest_pyfunc_call(pyfuncitem: Function) -> object | None: """ Pytest hook called before a test case is run. @@ -999,7 +991,7 @@ def _get_marked_loop_scope(asyncio_marker: Mark) -> _ScopeName: return scope -def _retrieve_scope_root(item: Union[Collector, Item], scope: str) -> Collector: +def _retrieve_scope_root(item: Collector | Item, scope: str) -> Collector: node_type_by_scope = { "class": Class, "module": Module, diff --git a/tests/async_fixtures/test_async_fixtures.py b/tests/async_fixtures/test_async_fixtures.py index 40012962..16478539 100644 --- a/tests/async_fixtures/test_async_fixtures.py +++ b/tests/async_fixtures/test_async_fixtures.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import asyncio import unittest.mock diff --git a/tests/async_fixtures/test_async_fixtures_scope.py b/tests/async_fixtures/test_async_fixtures_scope.py index a25934a8..7fbed781 100644 --- a/tests/async_fixtures/test_async_fixtures_scope.py +++ b/tests/async_fixtures/test_async_fixtures_scope.py @@ -3,6 +3,8 @@ module-scoped too. """ +from __future__ import annotations + import asyncio import pytest diff --git a/tests/async_fixtures/test_async_fixtures_with_finalizer.py b/tests/async_fixtures/test_async_fixtures_with_finalizer.py index 8efc8fc4..199ecbca 100644 --- a/tests/async_fixtures/test_async_fixtures_with_finalizer.py +++ b/tests/async_fixtures/test_async_fixtures_with_finalizer.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import asyncio import functools diff --git a/tests/async_fixtures/test_async_gen_fixtures.py b/tests/async_fixtures/test_async_gen_fixtures.py index 2b198f2b..ddc2f5be 100644 --- a/tests/async_fixtures/test_async_gen_fixtures.py +++ b/tests/async_fixtures/test_async_gen_fixtures.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import unittest.mock import pytest diff --git a/tests/async_fixtures/test_nested.py b/tests/async_fixtures/test_nested.py index da7ee3a1..72b5129a 100644 --- a/tests/async_fixtures/test_nested.py +++ b/tests/async_fixtures/test_nested.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import asyncio import pytest diff --git a/tests/async_fixtures/test_parametrized_loop.py b/tests/async_fixtures/test_parametrized_loop.py index 2bdbe5e8..ca2cb5c7 100644 --- a/tests/async_fixtures/test_parametrized_loop.py +++ b/tests/async_fixtures/test_parametrized_loop.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from textwrap import dedent from pytest import Pytester diff --git a/tests/async_fixtures/test_shared_module_fixture.py b/tests/async_fixtures/test_shared_module_fixture.py index 9b0ad540..3295c83a 100644 --- a/tests/async_fixtures/test_shared_module_fixture.py +++ b/tests/async_fixtures/test_shared_module_fixture.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from textwrap import dedent from pytest import Pytester diff --git a/tests/conftest.py b/tests/conftest.py index 4aa8c89a..76e2026f 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import asyncio import pytest diff --git a/tests/hypothesis/test_base.py b/tests/hypothesis/test_base.py index ee87a724..4b185f62 100644 --- a/tests/hypothesis/test_base.py +++ b/tests/hypothesis/test_base.py @@ -3,6 +3,8 @@ sync shim for Hypothesis. """ +from __future__ import annotations + from textwrap import dedent import pytest diff --git a/tests/loop_fixture_scope/conftest.py b/tests/loop_fixture_scope/conftest.py index 6b9a7649..4e8b06de 100644 --- a/tests/loop_fixture_scope/conftest.py +++ b/tests/loop_fixture_scope/conftest.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import asyncio import pytest diff --git a/tests/loop_fixture_scope/test_loop_fixture_scope.py b/tests/loop_fixture_scope/test_loop_fixture_scope.py index eb4be8c9..eb1bae58 100644 --- a/tests/loop_fixture_scope/test_loop_fixture_scope.py +++ b/tests/loop_fixture_scope/test_loop_fixture_scope.py @@ -1,5 +1,7 @@ """Unit tests for overriding the event loop with a larger scoped one.""" +from __future__ import annotations + import asyncio import pytest diff --git a/tests/markers/test_class_scope.py b/tests/markers/test_class_scope.py index edce31f6..4bddb4b8 100644 --- a/tests/markers/test_class_scope.py +++ b/tests/markers/test_class_scope.py @@ -1,5 +1,7 @@ """Test if pytestmark works when defined on a class.""" +from __future__ import annotations + import asyncio from textwrap import dedent diff --git a/tests/markers/test_function_scope.py b/tests/markers/test_function_scope.py index 75487b5d..c17a6225 100644 --- a/tests/markers/test_function_scope.py +++ b/tests/markers/test_function_scope.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from textwrap import dedent from pytest import Pytester diff --git a/tests/markers/test_invalid_arguments.py b/tests/markers/test_invalid_arguments.py index a4f4b070..89a1ac64 100644 --- a/tests/markers/test_invalid_arguments.py +++ b/tests/markers/test_invalid_arguments.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from textwrap import dedent import pytest diff --git a/tests/markers/test_module_scope.py b/tests/markers/test_module_scope.py index 12515f23..7dbdbb7f 100644 --- a/tests/markers/test_module_scope.py +++ b/tests/markers/test_module_scope.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from textwrap import dedent from pytest import Pytester diff --git a/tests/markers/test_package_scope.py b/tests/markers/test_package_scope.py index bd3e4ac7..204238a4 100644 --- a/tests/markers/test_package_scope.py +++ b/tests/markers/test_package_scope.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from textwrap import dedent from pytest import Pytester diff --git a/tests/markers/test_session_scope.py b/tests/markers/test_session_scope.py index 3bc38a4f..70e191b2 100644 --- a/tests/markers/test_session_scope.py +++ b/tests/markers/test_session_scope.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from textwrap import dedent from pytest import Pytester diff --git a/tests/modes/test_auto_mode.py b/tests/modes/test_auto_mode.py index f41c9d1a..21c48d87 100644 --- a/tests/modes/test_auto_mode.py +++ b/tests/modes/test_auto_mode.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from textwrap import dedent from pytest import Pytester diff --git a/tests/modes/test_strict_mode.py b/tests/modes/test_strict_mode.py index b8232d05..c5a7351a 100644 --- a/tests/modes/test_strict_mode.py +++ b/tests/modes/test_strict_mode.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from textwrap import dedent from pytest import Pytester diff --git a/tests/test_asyncio_fixture.py b/tests/test_asyncio_fixture.py index 4bdabce2..91e5d8d4 100644 --- a/tests/test_asyncio_fixture.py +++ b/tests/test_asyncio_fixture.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import asyncio from textwrap import dedent diff --git a/tests/test_asyncio_mark.py b/tests/test_asyncio_mark.py index 20ac173d..e22be989 100644 --- a/tests/test_asyncio_mark.py +++ b/tests/test_asyncio_mark.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from textwrap import dedent from pytest import Pytester diff --git a/tests/test_dependent_fixtures.py b/tests/test_dependent_fixtures.py index dc70fe9c..2e53700a 100644 --- a/tests/test_dependent_fixtures.py +++ b/tests/test_dependent_fixtures.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import asyncio import pytest diff --git a/tests/test_doctest.py b/tests/test_doctest.py index 3795a4d7..d175789e 100644 --- a/tests/test_doctest.py +++ b/tests/test_doctest.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from textwrap import dedent from pytest import Pytester diff --git a/tests/test_event_loop_fixture.py b/tests/test_event_loop_fixture.py index aaf591c9..21785075 100644 --- a/tests/test_event_loop_fixture.py +++ b/tests/test_event_loop_fixture.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from textwrap import dedent from pytest import Pytester diff --git a/tests/test_event_loop_fixture_finalizer.py b/tests/test_event_loop_fixture_finalizer.py index 4306c33d..17cc85b9 100644 --- a/tests/test_event_loop_fixture_finalizer.py +++ b/tests/test_event_loop_fixture_finalizer.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from textwrap import dedent from pytest import Pytester diff --git a/tests/test_event_loop_fixture_override_deprecation.py b/tests/test_event_loop_fixture_override_deprecation.py index 683f0963..04859ef7 100644 --- a/tests/test_event_loop_fixture_override_deprecation.py +++ b/tests/test_event_loop_fixture_override_deprecation.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from textwrap import dedent from pytest import Pytester diff --git a/tests/test_explicit_event_loop_fixture_request.py b/tests/test_explicit_event_loop_fixture_request.py index 382fbf7c..c685ad84 100644 --- a/tests/test_explicit_event_loop_fixture_request.py +++ b/tests/test_explicit_event_loop_fixture_request.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from textwrap import dedent from pytest import Pytester diff --git a/tests/test_fixture_loop_scopes.py b/tests/test_fixture_loop_scopes.py index f0271e59..a9ce4b35 100644 --- a/tests/test_fixture_loop_scopes.py +++ b/tests/test_fixture_loop_scopes.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from textwrap import dedent import pytest diff --git a/tests/test_import.py b/tests/test_import.py index f1bf3caf..2272704a 100644 --- a/tests/test_import.py +++ b/tests/test_import.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from textwrap import dedent from pytest import Pytester diff --git a/tests/test_is_async_test.py b/tests/test_is_async_test.py index d69a54f6..f99dc0d9 100644 --- a/tests/test_is_async_test.py +++ b/tests/test_is_async_test.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from textwrap import dedent from pytest import Pytester diff --git a/tests/test_multiloop.py b/tests/test_multiloop.py index c3713cc9..e6c852b9 100644 --- a/tests/test_multiloop.py +++ b/tests/test_multiloop.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from textwrap import dedent from pytest import Pytester diff --git a/tests/test_port_factories.py b/tests/test_port_factories.py index cbbd47b4..713d747e 100644 --- a/tests/test_port_factories.py +++ b/tests/test_port_factories.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from textwrap import dedent from pytest import Pytester diff --git a/tests/test_simple.py b/tests/test_simple.py index c39dfda8..b8a34fb2 100644 --- a/tests/test_simple.py +++ b/tests/test_simple.py @@ -1,5 +1,7 @@ """Quick'n'dirty unit tests for provided fixtures and markers.""" +from __future__ import annotations + import asyncio from textwrap import dedent diff --git a/tests/test_skips.py b/tests/test_skips.py index 96582ac0..d32273cd 100644 --- a/tests/test_skips.py +++ b/tests/test_skips.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from textwrap import dedent from pytest import Pytester diff --git a/tests/test_subprocess.py b/tests/test_subprocess.py index 3d91e7b1..c32ba964 100644 --- a/tests/test_subprocess.py +++ b/tests/test_subprocess.py @@ -1,5 +1,7 @@ """Tests for using subprocesses in tests.""" +from __future__ import annotations + import asyncio.subprocess import sys diff --git a/tools/get-version.py b/tools/get-version.py index c29081b9..9d24b6a5 100644 --- a/tools/get-version.py +++ b/tools/get-version.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import json import sys from importlib import metadata From 8c4152df9dec6c166078277e64f058699e0d5360 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Oct 2024 11:27:05 +0000 Subject: [PATCH 115/226] Build(deps): Bump hypothesis in /dependencies/default Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.112.4 to 6.115.5. - [Release notes](https://github.com/HypothesisWorks/hypothesis/releases) - [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.112.4...hypothesis-python-6.115.5) --- updated-dependencies: - dependency-name: hypothesis dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index f9d30444..1ac0512a 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -1,7 +1,7 @@ attrs==24.2.0 coverage==7.6.1 exceptiongroup==1.2.2 -hypothesis==6.112.4 +hypothesis==6.115.5 iniconfig==2.0.0 packaging==24.1 pluggy==1.5.0 From e40623da6bac37ddb90fba21a3ab72a66a38bd85 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Oct 2024 11:27:07 +0000 Subject: [PATCH 116/226] Build(deps): Bump coverage from 7.6.1 to 7.6.4 in /dependencies/default Bumps [coverage](https://github.com/nedbat/coveragepy) from 7.6.1 to 7.6.4. - [Release notes](https://github.com/nedbat/coveragepy/releases) - [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst) - [Commits](https://github.com/nedbat/coveragepy/compare/7.6.1...7.6.4) --- updated-dependencies: - dependency-name: coverage dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index 1ac0512a..e9726bcb 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -1,5 +1,5 @@ attrs==24.2.0 -coverage==7.6.1 +coverage==7.6.4 exceptiongroup==1.2.2 hypothesis==6.115.5 iniconfig==2.0.0 From 2609b7a821b846f19d4a05c4d1f2ed6ab85d05b5 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Mon, 28 Oct 2024 13:07:24 +0100 Subject: [PATCH 117/226] [pre-commit] pre-commit autoupdate --- .pre-commit-config.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index bef06f2b..27384790 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,7 +6,7 @@ repos: - id: check-merge-conflict exclude: rst$ - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.7.0 + rev: v0.7.1 hooks: - id: ruff args: [--fix] @@ -15,7 +15,7 @@ repos: hooks: - id: yesqa - repo: https://github.com/Zac-HD/shed - rev: 2024.3.1 + rev: 2024.10.1 hooks: - id: shed args: @@ -42,7 +42,7 @@ repos: - id: check-yaml - id: debug-statements - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.11.2 + rev: v1.13.0 hooks: - id: mypy exclude: ^(docs|tests)/.* @@ -65,11 +65,11 @@ repos: - 'SC1004:' stages: [manual] - repo: https://github.com/sirosen/check-jsonschema - rev: 0.29.3 + rev: 0.29.4 hooks: - id: check-github-actions - repo: https://github.com/tox-dev/pyproject-fmt - rev: 2.3.1 + rev: v2.4.3 hooks: - id: pyproject-fmt # https://pyproject-fmt.readthedocs.io/en/latest/#calculating-max-supported-python-version From 38d4bc43a57b72b96913bc4556e9d7f69ec2ba96 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 30 Oct 2024 18:05:06 +0000 Subject: [PATCH 118/226] Build(deps): Bump pypa/gh-action-pypi-publish from 1.10.3 to 1.11.0 Bumps [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) from 1.10.3 to 1.11.0. - [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases) - [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/v1.10.3...v1.11.0) --- updated-dependencies: - dependency-name: pypa/gh-action-pypi-publish dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2b4cb161..a6e60776 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -151,7 +151,7 @@ jobs: run: | pandoc -s -o README.md README.rst - name: PyPI upload - uses: pypa/gh-action-pypi-publish@v1.10.3 + uses: pypa/gh-action-pypi-publish@v1.11.0 with: attestations: true packages-dir: dist From f4fbf2bbf59b04954446d110c105883ff6d9304b Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Wed, 30 Oct 2024 20:32:41 +0100 Subject: [PATCH 119/226] ci: Use Python 3.13 release version for testing. --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a6e60776..99413c6c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -62,7 +62,7 @@ jobs: strategy: matrix: os: [ubuntu, windows] - python-version: ['3.9', '3.10', '3.11', '3.12', 3.13.0-beta.3] + python-version: ['3.9', '3.10', '3.11', '3.12', '3.13'] steps: - uses: actions/checkout@v4 From 9ba2b3c2da63edaebb0e039d93c633ac2eae09be Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Wed, 30 Oct 2024 20:34:20 +0100 Subject: [PATCH 120/226] ci: Use Python 3.13 as default version for tools. --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 99413c6c..138bf478 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -11,7 +11,7 @@ on: workflow_dispatch: env: - PYTHON_LATEST: 3.12 + PYTHON_LATEST: 3.13 jobs: lint: From 858407fba036240c93bafd0184f219b0669f3114 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Nov 2024 18:36:34 +0000 Subject: [PATCH 121/226] Build(deps): Bump hypothesis in /dependencies/default Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.115.5 to 6.116.0. - [Release notes](https://github.com/HypothesisWorks/hypothesis/releases) - [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.115.5...hypothesis-python-6.116.0) --- updated-dependencies: - dependency-name: hypothesis dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index e9726bcb..86b75641 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -1,7 +1,7 @@ attrs==24.2.0 coverage==7.6.4 exceptiongroup==1.2.2 -hypothesis==6.115.5 +hypothesis==6.116.0 iniconfig==2.0.0 packaging==24.1 pluggy==1.5.0 From 575ebe162cf8d80958102b36275ea3de5a07c34d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 4 Nov 2024 23:19:34 +0000 Subject: [PATCH 122/226] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.7.1 → v0.7.2](https://github.com/astral-sh/ruff-pre-commit/compare/v0.7.1...v0.7.2) - [github.com/rhysd/actionlint: v1.7.3 → v1.7.4](https://github.com/rhysd/actionlint/compare/v1.7.3...v1.7.4) - [github.com/tox-dev/pyproject-fmt: v2.4.3 → v2.5.0](https://github.com/tox-dev/pyproject-fmt/compare/v2.4.3...v2.5.0) --- .pre-commit-config.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 27384790..28fa0f93 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,7 +6,7 @@ repos: - id: check-merge-conflict exclude: rst$ - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.7.1 + rev: v0.7.2 hooks: - id: ruff args: [--fix] @@ -53,7 +53,7 @@ repos: hooks: - id: python-use-type-annotations - repo: https://github.com/rhysd/actionlint - rev: v1.7.3 + rev: v1.7.4 hooks: - id: actionlint-docker args: @@ -69,7 +69,7 @@ repos: hooks: - id: check-github-actions - repo: https://github.com/tox-dev/pyproject-fmt - rev: v2.4.3 + rev: v2.5.0 hooks: - id: pyproject-fmt # https://pyproject-fmt.readthedocs.io/en/latest/#calculating-max-supported-python-version From adcae5bea72a9e16b8420d06e23b3915c6f82333 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 6 Nov 2024 18:51:38 +0000 Subject: [PATCH 123/226] Build(deps): Bump pypa/gh-action-pypi-publish from 1.11.0 to 1.12.0 Bumps [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) from 1.11.0 to 1.12.0. - [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases) - [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/v1.11.0...v1.12.0) --- updated-dependencies: - dependency-name: pypa/gh-action-pypi-publish dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 138bf478..d938a869 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -151,7 +151,7 @@ jobs: run: | pandoc -s -o README.md README.rst - name: PyPI upload - uses: pypa/gh-action-pypi-publish@v1.11.0 + uses: pypa/gh-action-pypi-publish@v1.12.0 with: attestations: true packages-dir: dist From a5a38ed161599258dfbae2d46241c00c78f0e4fc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 7 Nov 2024 18:04:52 +0000 Subject: [PATCH 124/226] Build(deps): Bump pypa/gh-action-pypi-publish from 1.12.0 to 1.12.2 Bumps [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) from 1.12.0 to 1.12.2. - [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases) - [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/v1.12.0...v1.12.2) --- updated-dependencies: - dependency-name: pypa/gh-action-pypi-publish dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d938a869..90d914fa 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -151,7 +151,7 @@ jobs: run: | pandoc -s -o README.md README.rst - name: PyPI upload - uses: pypa/gh-action-pypi-publish@v1.12.0 + uses: pypa/gh-action-pypi-publish@v1.12.2 with: attestations: true packages-dir: dist From 090fbfbb9dc2ced7e00b8ef2ece4dcf53acf1787 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Nov 2024 18:15:25 +0000 Subject: [PATCH 125/226] Build(deps): Bump hypothesis in /dependencies/default Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.116.0 to 6.118.7. - [Release notes](https://github.com/HypothesisWorks/hypothesis/releases) - [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.116.0...hypothesis-python-6.118.7) --- updated-dependencies: - dependency-name: hypothesis dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index 86b75641..7577faed 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -1,7 +1,7 @@ attrs==24.2.0 coverage==7.6.4 exceptiongroup==1.2.2 -hypothesis==6.116.0 +hypothesis==6.118.7 iniconfig==2.0.0 packaging==24.1 pluggy==1.5.0 From 05873403e0ecb6ffc34f7fa410ee9e0f2a2f8f35 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 11 Nov 2024 23:01:07 +0000 Subject: [PATCH 126/226] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.7.2 → v0.7.3](https://github.com/astral-sh/ruff-pre-commit/compare/v0.7.2...v0.7.3) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 28fa0f93..add14328 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,7 +6,7 @@ repos: - id: check-merge-conflict exclude: rst$ - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.7.2 + rev: v0.7.3 hooks: - id: ruff args: [--fix] From 40de086c501d438556734a02c04e335fa89f75ae Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Nov 2024 18:15:08 +0000 Subject: [PATCH 127/226] Build(deps): Bump codecov/codecov-action from 4 to 5 Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 4 to 5. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/v4...v5) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 90d914fa..e28488c3 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -120,7 +120,7 @@ jobs: coverage combine coverage xml - name: Upload coverage report - uses: codecov/codecov-action@v4 + uses: codecov/codecov-action@v5 with: files: coverage.xml fail_ci_if_error: true From 2462d869e6cc6c014a03d6a6e2bd0a7675ec1cda Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Fri, 15 Nov 2024 16:26:05 +0100 Subject: [PATCH 128/226] plugin.py: Fix typo --- pytest_asyncio/plugin.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pytest_asyncio/plugin.py b/pytest_asyncio/plugin.py index 1c81fee5..b4e6ab33 100644 --- a/pytest_asyncio/plugin.py +++ b/pytest_asyncio/plugin.py @@ -792,9 +792,9 @@ def pytest_fixture_setup( def _add_finalizers(fixturedef: FixtureDef, *finalizers: Callable[[], object]) -> None: """ - Regsiters the specified fixture finalizers in the fixture. + Registers the specified fixture finalizers in the fixture. - Finalizers need to specified in the exact order in which they should be invoked. + Finalizers need to be specified in the exact order in which they should be invoked. :param fixturedef: Fixture definition which finalizers should be added to :param finalizers: Finalizers to be added From a1c91abca18216b12bcb71dd2350f64e77f8885b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Nov 2024 18:07:43 +0000 Subject: [PATCH 129/226] Build(deps): Bump hypothesis in /dependencies/default Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.118.7 to 6.119.3. - [Release notes](https://github.com/HypothesisWorks/hypothesis/releases) - [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.118.7...hypothesis-python-6.119.3) --- updated-dependencies: - dependency-name: hypothesis dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index 7577faed..3082f87e 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -1,7 +1,7 @@ attrs==24.2.0 coverage==7.6.4 exceptiongroup==1.2.2 -hypothesis==6.118.7 +hypothesis==6.119.3 iniconfig==2.0.0 packaging==24.1 pluggy==1.5.0 From 87f51f8050fa7ded144e5cd134f50493e4b3d95b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Nov 2024 19:16:48 +0000 Subject: [PATCH 130/226] Build(deps): Bump coverage from 7.6.4 to 7.6.7 in /dependencies/default Bumps [coverage](https://github.com/nedbat/coveragepy) from 7.6.4 to 7.6.7. - [Release notes](https://github.com/nedbat/coveragepy/releases) - [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst) - [Commits](https://github.com/nedbat/coveragepy/compare/7.6.4...7.6.7) --- updated-dependencies: - dependency-name: coverage dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index 3082f87e..82ea85d6 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -1,5 +1,5 @@ attrs==24.2.0 -coverage==7.6.4 +coverage==7.6.7 exceptiongroup==1.2.2 hypothesis==6.119.3 iniconfig==2.0.0 From 6aa6e05892c75d214fa703f33da51e3f3c657c81 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Nov 2024 18:07:30 +0000 Subject: [PATCH 131/226] Build(deps): Bump tomli from 2.0.2 to 2.1.0 in /dependencies/default Bumps [tomli](https://github.com/hukkin/tomli) from 2.0.2 to 2.1.0. - [Changelog](https://github.com/hukkin/tomli/blob/master/CHANGELOG.md) - [Commits](https://github.com/hukkin/tomli/compare/2.0.2...2.1.0) --- updated-dependencies: - dependency-name: tomli dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index 82ea85d6..d0e6676e 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -7,5 +7,5 @@ packaging==24.1 pluggy==1.5.0 pytest==8.3.3 sortedcontainers==2.4.0 -tomli==2.0.2 +tomli==2.1.0 typing_extensions==4.12.2 From 1057723777f7756c51e25fa5649059e6dc7814ec Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 18 Nov 2024 23:04:48 +0000 Subject: [PATCH 132/226] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.7.3 → v0.7.4](https://github.com/astral-sh/ruff-pre-commit/compare/v0.7.3...v0.7.4) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index add14328..a918ae11 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,7 +6,7 @@ repos: - id: check-merge-conflict exclude: rst$ - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.7.3 + rev: v0.7.4 hooks: - id: ruff args: [--fix] From fef439f286e79127aab2067861d4e27af2022459 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Nov 2024 19:01:10 +0000 Subject: [PATCH 133/226] Build(deps): Bump sphinx-rtd-theme in /dependencies/docs Bumps [sphinx-rtd-theme](https://github.com/readthedocs/sphinx_rtd_theme) from 3.0.1 to 3.0.2. - [Changelog](https://github.com/readthedocs/sphinx_rtd_theme/blob/master/docs/changelog.rst) - [Commits](https://github.com/readthedocs/sphinx_rtd_theme/compare/3.0.1...3.0.2) --- updated-dependencies: - dependency-name: sphinx-rtd-theme dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dependencies/docs/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/docs/constraints.txt b/dependencies/docs/constraints.txt index b7be8005..2682c504 100644 --- a/dependencies/docs/constraints.txt +++ b/dependencies/docs/constraints.txt @@ -12,7 +12,7 @@ Pygments==2.18.0 requests==2.32.3 snowballstemmer==2.2.0 Sphinx==8.0.2 -sphinx-rtd-theme==3.0.1 +sphinx-rtd-theme==3.0.2 sphinxcontrib-applehelp==2.0.0 sphinxcontrib-devhelp==2.0.0 sphinxcontrib-htmlhelp==2.1.0 From 96d4fb4722d8e477d9fe8a7b18f2fbaae383ecd3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Nov 2024 19:03:49 +0000 Subject: [PATCH 134/226] Build(deps): Bump packaging from 24.1 to 24.2 in /dependencies/docs Bumps [packaging](https://github.com/pypa/packaging) from 24.1 to 24.2. - [Release notes](https://github.com/pypa/packaging/releases) - [Changelog](https://github.com/pypa/packaging/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pypa/packaging/compare/24.1...24.2) --- updated-dependencies: - dependency-name: packaging dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- dependencies/docs/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/docs/constraints.txt b/dependencies/docs/constraints.txt index 2682c504..d79e0456 100644 --- a/dependencies/docs/constraints.txt +++ b/dependencies/docs/constraints.txt @@ -7,7 +7,7 @@ idna==3.10 imagesize==1.4.1 Jinja2==3.1.4 MarkupSafe==3.0.2 -packaging==24.1 +packaging==24.2 Pygments==2.18.0 requests==2.32.3 snowballstemmer==2.2.0 From cf622310ee0c4dde06eb7a2870421e608dd6ab73 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Nov 2024 19:46:03 +0000 Subject: [PATCH 135/226] Build(deps): Bump packaging from 24.1 to 24.2 in /dependencies/default Bumps [packaging](https://github.com/pypa/packaging) from 24.1 to 24.2. - [Release notes](https://github.com/pypa/packaging/releases) - [Changelog](https://github.com/pypa/packaging/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pypa/packaging/compare/24.1...24.2) --- updated-dependencies: - dependency-name: packaging dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index d0e6676e..f53747c1 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -3,7 +3,7 @@ coverage==7.6.7 exceptiongroup==1.2.2 hypothesis==6.119.3 iniconfig==2.0.0 -packaging==24.1 +packaging==24.2 pluggy==1.5.0 pytest==8.3.3 sortedcontainers==2.4.0 From ba8c0a1daf4f3f0bda48306b42e0b73c4b6e473d Mon Sep 17 00:00:00 2001 From: jakkdl Date: Tue, 5 Nov 2024 15:59:39 +0100 Subject: [PATCH 136/226] feat: Warn if asyncio test requests async pytest fixture in strict mode fix test make it raise PytestDeprecationWarning instead add changelog entry docs: Changed release date of v0.25.0 to UNRELEASED. --- docs/reference/changelog.rst | 4 ++ pytest_asyncio/plugin.py | 27 +++++++++- tests/modes/test_strict_mode.py | 87 +++++++++++++++++++++++++++++++++ 3 files changed, 117 insertions(+), 1 deletion(-) diff --git a/docs/reference/changelog.rst b/docs/reference/changelog.rst index 77cf3451..285aadf5 100644 --- a/docs/reference/changelog.rst +++ b/docs/reference/changelog.rst @@ -2,6 +2,10 @@ Changelog ========= +0.25.0 (UNRELEASED) +=================== +- Deprecated: Added warning when asyncio test requests async ``@pytest.fixture`` in strict mode. This will become an error in a future version of flake8-asyncio. `#979 `_ + 0.24.0 (2024-08-22) =================== - BREAKING: Updated minimum supported pytest version to v8.2.0 diff --git a/pytest_asyncio/plugin.py b/pytest_asyncio/plugin.py index b4e6ab33..0261d12e 100644 --- a/pytest_asyncio/plugin.py +++ b/pytest_asyncio/plugin.py @@ -880,7 +880,32 @@ def pytest_pyfunc_call(pyfuncitem: Function) -> object | None: """ if pyfuncitem.get_closest_marker("asyncio") is not None: if isinstance(pyfuncitem, PytestAsyncioFunction): - pass + asyncio_mode = _get_asyncio_mode(pyfuncitem.config) + for fixname, fixtures in pyfuncitem._fixtureinfo.name2fixturedefs.items(): + # name2fixturedefs is a dict between fixture name and a list of matching + # fixturedefs. The last entry in the list is closest and the one used. + func = fixtures[-1].func + if ( + _is_coroutine_or_asyncgen(func) + and not _is_asyncio_fixture_function(func) + and asyncio_mode == Mode.STRICT + ): + warnings.warn( + PytestDeprecationWarning( + f"asyncio test {pyfuncitem.name!r} requested async " + "@pytest.fixture " + f"{fixname!r} in strict mode. " + "You might want to use @pytest_asyncio.fixture or switch " + "to auto mode. " + "This will become an error in future versions of " + "flake8-asyncio." + ), + stacklevel=1, + ) + # no stacklevel points at the users code, so we set stacklevel=1 + # so it at least indicates that it's the plugin complaining. + # Pytest gives the test file & name in the warnings summary at least + else: pyfuncitem.warn( pytest.PytestWarning( diff --git a/tests/modes/test_strict_mode.py b/tests/modes/test_strict_mode.py index c5a7351a..52cbb251 100644 --- a/tests/modes/test_strict_mode.py +++ b/tests/modes/test_strict_mode.py @@ -124,3 +124,90 @@ async def test_anything(any_fixture): "*coroutine 'any_fixture' was never awaited*", ], ) + + +def test_strict_mode_marked_test_unmarked_fixture_warning(pytester: Pytester): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") + pytester.makepyfile( + dedent( + """\ + import pytest + + # Not using pytest_asyncio.fixture + @pytest.fixture() + async def any_fixture(): + pass + + @pytest.mark.asyncio + async def test_anything(any_fixture): + # suppress unawaited coroutine warning + try: + any_fixture.send(None) + except StopIteration: + pass + """ + ) + ) + result = pytester.runpytest_subprocess("--asyncio-mode=strict", "-W default") + result.assert_outcomes(passed=1, failed=0, skipped=0, warnings=1) + result.stdout.fnmatch_lines( + [ + "*warnings summary*", + ( + "test_strict_mode_marked_test_unmarked_fixture_warning.py::" + "test_anything" + ), + ( + "*/pytest_asyncio/plugin.py:*: PytestDeprecationWarning: " + "asyncio test 'test_anything' requested async " + "@pytest.fixture 'any_fixture' in strict mode. " + "You might want to use @pytest_asyncio.fixture or switch to " + "auto mode. " + "This will become an error in future versions of flake8-asyncio." + ), + ], + ) + + +# autouse is not handled in any special way currently +def test_strict_mode_marked_test_unmarked_autouse_fixture_warning(pytester: Pytester): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") + pytester.makepyfile( + dedent( + """\ + import pytest + + # Not using pytest_asyncio.fixture + @pytest.fixture(autouse=True) + async def any_fixture(): + pass + + @pytest.mark.asyncio + async def test_anything(any_fixture): + # suppress unawaited coroutine warning + try: + any_fixture.send(None) + except StopIteration: + pass + """ + ) + ) + result = pytester.runpytest_subprocess("--asyncio-mode=strict", "-W default") + result.assert_outcomes(passed=1, warnings=1) + result.stdout.fnmatch_lines( + [ + "*warnings summary*", + ( + "test_strict_mode_marked_test_unmarked_autouse_fixture_warning.py::" + "test_anything" + ), + ( + "*/pytest_asyncio/plugin.py:*: PytestDeprecationWarning: " + "*asyncio test 'test_anything' requested async " + "@pytest.fixture 'any_fixture' in strict mode. " + "You might want to use @pytest_asyncio.fixture or switch to " + "auto mode. " + "This will become an error in future versions of flake8-asyncio." + ), + ], + ) From 05f7284479e907553fe76af8b64c9f1f635fad66 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Nov 2024 19:19:24 +0000 Subject: [PATCH 137/226] Build(deps): Bump hypothesis in /dependencies/default Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.119.3 to 6.119.4. - [Release notes](https://github.com/HypothesisWorks/hypothesis/releases) - [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.119.3...hypothesis-python-6.119.4) --- updated-dependencies: - dependency-name: hypothesis dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index f53747c1..e3ad6240 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -1,7 +1,7 @@ attrs==24.2.0 coverage==7.6.7 exceptiongroup==1.2.2 -hypothesis==6.119.3 +hypothesis==6.119.4 iniconfig==2.0.0 packaging==24.2 pluggy==1.5.0 From d31c0cba9b6617f90f1cbd685a54f13a0f80650e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Nov 2024 19:19:17 +0000 Subject: [PATCH 138/226] Build(deps): Bump coverage from 7.6.7 to 7.6.8 in /dependencies/default Bumps [coverage](https://github.com/nedbat/coveragepy) from 7.6.7 to 7.6.8. - [Release notes](https://github.com/nedbat/coveragepy/releases) - [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst) - [Commits](https://github.com/nedbat/coveragepy/compare/7.6.7...7.6.8) --- updated-dependencies: - dependency-name: coverage dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index e3ad6240..5bcdd948 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -1,5 +1,5 @@ attrs==24.2.0 -coverage==7.6.7 +coverage==7.6.8 exceptiongroup==1.2.2 hypothesis==6.119.4 iniconfig==2.0.0 From 148f2f20e31d350758048f5c93dea62de850cdba Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 25 Nov 2024 22:57:15 +0000 Subject: [PATCH 139/226] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.7.4 → v0.8.0](https://github.com/astral-sh/ruff-pre-commit/compare/v0.7.4...v0.8.0) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a918ae11..28394c74 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,7 +6,7 @@ repos: - id: check-merge-conflict exclude: rst$ - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.7.4 + rev: v0.8.0 hooks: - id: ruff args: [--fix] From cc81ef5c6401983c5a0f22d353c0be4cede71683 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Dec 2024 18:48:04 +0000 Subject: [PATCH 140/226] Build(deps): Bump pytest from 8.3.3 to 8.3.4 in /dependencies/default Bumps [pytest](https://github.com/pytest-dev/pytest) from 8.3.3 to 8.3.4. - [Release notes](https://github.com/pytest-dev/pytest/releases) - [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest/compare/8.3.3...8.3.4) --- updated-dependencies: - dependency-name: pytest dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index 5bcdd948..551fb6f7 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -5,7 +5,7 @@ hypothesis==6.119.4 iniconfig==2.0.0 packaging==24.2 pluggy==1.5.0 -pytest==8.3.3 +pytest==8.3.4 sortedcontainers==2.4.0 tomli==2.1.0 typing_extensions==4.12.2 From 33e95e19b6f4240d05d7ed6a9d9212e617c0e83b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Dec 2024 18:48:01 +0000 Subject: [PATCH 141/226] Build(deps): Bump hypothesis in /dependencies/default Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.119.4 to 6.122.1. - [Release notes](https://github.com/HypothesisWorks/hypothesis/releases) - [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.119.4...hypothesis-python-6.122.1) --- updated-dependencies: - dependency-name: hypothesis dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index 551fb6f7..95ba7620 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -1,7 +1,7 @@ attrs==24.2.0 coverage==7.6.8 exceptiongroup==1.2.2 -hypothesis==6.119.4 +hypothesis==6.122.1 iniconfig==2.0.0 packaging==24.2 pluggy==1.5.0 From 998e8558abd52988d2d2f06f1b9cdedcc3a50a6c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Dec 2024 18:47:51 +0000 Subject: [PATCH 142/226] Build(deps): Bump tomli from 2.1.0 to 2.2.1 in /dependencies/default Bumps [tomli](https://github.com/hukkin/tomli) from 2.1.0 to 2.2.1. - [Changelog](https://github.com/hukkin/tomli/blob/master/CHANGELOG.md) - [Commits](https://github.com/hukkin/tomli/compare/2.1.0...2.2.1) --- updated-dependencies: - dependency-name: tomli dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index 95ba7620..728dadac 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -7,5 +7,5 @@ packaging==24.2 pluggy==1.5.0 pytest==8.3.4 sortedcontainers==2.4.0 -tomli==2.1.0 +tomli==2.2.1 typing_extensions==4.12.2 From 3f0fdfb4e4a16dd09bf1a570d5b7a745f54427b9 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 2 Dec 2024 23:33:41 +0000 Subject: [PATCH 143/226] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.8.0 → v0.8.1](https://github.com/astral-sh/ruff-pre-commit/compare/v0.8.0...v0.8.1) - [github.com/sirosen/check-jsonschema: 0.29.4 → 0.30.0](https://github.com/sirosen/check-jsonschema/compare/0.29.4...0.30.0) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 28394c74..60874c72 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,7 +6,7 @@ repos: - id: check-merge-conflict exclude: rst$ - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.8.0 + rev: v0.8.1 hooks: - id: ruff args: [--fix] @@ -65,7 +65,7 @@ repos: - 'SC1004:' stages: [manual] - repo: https://github.com/sirosen/check-jsonschema - rev: 0.29.4 + rev: 0.30.0 hooks: - id: check-github-actions - repo: https://github.com/tox-dev/pyproject-fmt From dbf999177fcba27f6ab47676ce979fb3af9dba30 Mon Sep 17 00:00:00 2001 From: Tushar Sadhwani Date: Tue, 3 Dec 2024 03:05:49 +0530 Subject: [PATCH 144/226] Rename 'scope' to 'loop_scope' in error message fix failing test Add changelog entry --- docs/reference/changelog.rst | 1 + pytest_asyncio/plugin.py | 2 +- tests/markers/test_invalid_arguments.py | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/reference/changelog.rst b/docs/reference/changelog.rst index 285aadf5..83017799 100644 --- a/docs/reference/changelog.rst +++ b/docs/reference/changelog.rst @@ -5,6 +5,7 @@ Changelog 0.25.0 (UNRELEASED) =================== - Deprecated: Added warning when asyncio test requests async ``@pytest.fixture`` in strict mode. This will become an error in a future version of flake8-asyncio. `#979 `_ +- Updates the error message about `pytest.mark.asyncio`'s `scope` keyword argument to say `loop_scope` instead. `#1004 `_ 0.24.0 (2024-08-22) =================== diff --git a/pytest_asyncio/plugin.py b/pytest_asyncio/plugin.py index 0261d12e..c490e10c 100644 --- a/pytest_asyncio/plugin.py +++ b/pytest_asyncio/plugin.py @@ -1004,7 +1004,7 @@ def _get_marked_loop_scope(asyncio_marker: Mark) -> _ScopeName: if asyncio_marker.args or ( asyncio_marker.kwargs and set(asyncio_marker.kwargs) - {"loop_scope", "scope"} ): - raise ValueError("mark.asyncio accepts only a keyword argument 'scope'.") + raise ValueError("mark.asyncio accepts only a keyword argument 'loop_scope'.") if "scope" in asyncio_marker.kwargs: if "loop_scope" in asyncio_marker.kwargs: raise pytest.UsageError(_DUPLICATE_LOOP_SCOPE_DEFINITION_ERROR) diff --git a/tests/markers/test_invalid_arguments.py b/tests/markers/test_invalid_arguments.py index 89a1ac64..2d5c3552 100644 --- a/tests/markers/test_invalid_arguments.py +++ b/tests/markers/test_invalid_arguments.py @@ -62,7 +62,7 @@ async def test_anything(): result = pytester.runpytest_subprocess() result.assert_outcomes(errors=1) result.stdout.fnmatch_lines( - ["*ValueError: mark.asyncio accepts only a keyword argument 'scope'*"] + ["*ValueError: mark.asyncio accepts only a keyword argument 'loop_scope'*"] ) From a1cd86122f9a289f25c1ea37a5c0eb3a99f2ba7a Mon Sep 17 00:00:00 2001 From: Mark <6531552+MarkusBiggus@users.noreply.github.com> Date: Mon, 18 Nov 2024 16:17:31 +1000 Subject: [PATCH 145/226] display full param name asyncio_default_fixture_loop_scope --- docs/reference/changelog.rst | 1 + pytest_asyncio/plugin.py | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/reference/changelog.rst b/docs/reference/changelog.rst index 83017799..d29fa184 100644 --- a/docs/reference/changelog.rst +++ b/docs/reference/changelog.rst @@ -6,6 +6,7 @@ Changelog =================== - Deprecated: Added warning when asyncio test requests async ``@pytest.fixture`` in strict mode. This will become an error in a future version of flake8-asyncio. `#979 `_ - Updates the error message about `pytest.mark.asyncio`'s `scope` keyword argument to say `loop_scope` instead. `#1004 `_ +- Verbose log displays correct parameter name: asyncio_default_fixture_loop_scope `#990 `_ 0.24.0 (2024-08-22) =================== diff --git a/pytest_asyncio/plugin.py b/pytest_asyncio/plugin.py index c490e10c..d3e006d8 100644 --- a/pytest_asyncio/plugin.py +++ b/pytest_asyncio/plugin.py @@ -216,7 +216,9 @@ def pytest_report_header(config: Config) -> list[str]: """Add asyncio config to pytest header.""" mode = _get_asyncio_mode(config) default_loop_scope = config.getini("asyncio_default_fixture_loop_scope") - return [f"asyncio: mode={mode}, default_loop_scope={default_loop_scope}"] + return [ + f"asyncio: mode={mode}, asyncio_default_fixture_loop_scope={default_loop_scope}" + ] def _preprocess_async_fixtures( From 34be548a367044cced1320e3a757052b4245e4ee Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Dec 2024 18:18:57 +0000 Subject: [PATCH 146/226] Build(deps): Bump pypa/gh-action-pypi-publish from 1.12.2 to 1.12.3 Bumps [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) from 1.12.2 to 1.12.3. - [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases) - [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/v1.12.2...v1.12.3) --- updated-dependencies: - dependency-name: pypa/gh-action-pypi-publish dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e28488c3..12348ae1 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -151,7 +151,7 @@ jobs: run: | pandoc -s -o README.md README.rst - name: PyPI upload - uses: pypa/gh-action-pypi-publish@v1.12.2 + uses: pypa/gh-action-pypi-publish@v1.12.3 with: attestations: true packages-dir: dist From 5b01b2dd090a81a7a41647c89d0af32635b6c314 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 9 Dec 2024 23:06:52 +0000 Subject: [PATCH 147/226] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.8.1 → v0.8.2](https://github.com/astral-sh/ruff-pre-commit/compare/v0.8.1...v0.8.2) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 60874c72..dc20cbd5 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,7 +6,7 @@ repos: - id: check-merge-conflict exclude: rst$ - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.8.1 + rev: v0.8.2 hooks: - id: ruff args: [--fix] From 669c50b0b14cf764f5d3c3c54e23e2eb151a3bbb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Dec 2024 18:14:53 +0000 Subject: [PATCH 148/226] Build(deps): Bump coverage from 7.6.8 to 7.6.9 in /dependencies/default Bumps [coverage](https://github.com/nedbat/coveragepy) from 7.6.8 to 7.6.9. - [Release notes](https://github.com/nedbat/coveragepy/releases) - [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst) - [Commits](https://github.com/nedbat/coveragepy/compare/7.6.8...7.6.9) --- updated-dependencies: - dependency-name: coverage dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index 728dadac..1e1a6467 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -1,5 +1,5 @@ attrs==24.2.0 -coverage==7.6.8 +coverage==7.6.9 exceptiongroup==1.2.2 hypothesis==6.122.1 iniconfig==2.0.0 From c4c1b482de0472d91b40ba0c07935d704c483bce Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Dec 2024 18:14:48 +0000 Subject: [PATCH 149/226] Build(deps): Bump hypothesis in /dependencies/default Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.122.1 to 6.122.3. - [Release notes](https://github.com/HypothesisWorks/hypothesis/releases) - [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.122.1...hypothesis-python-6.122.3) --- updated-dependencies: - dependency-name: hypothesis dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index 1e1a6467..9cd79a18 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -1,7 +1,7 @@ attrs==24.2.0 coverage==7.6.9 exceptiongroup==1.2.2 -hypothesis==6.122.1 +hypothesis==6.122.3 iniconfig==2.0.0 packaging==24.2 pluggy==1.5.0 From ebbd602687c46e34089963e4a06183e5f9774db0 Mon Sep 17 00:00:00 2001 From: jfs Date: Mon, 9 Dec 2024 13:47:13 +0300 Subject: [PATCH 150/226] docs: describe when UsageError is raised for loop_scope="class" marker before that: docs claimed (erroneously) the opposite of the actual (and intended) behavior. --- docs/reference/markers/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference/markers/index.rst b/docs/reference/markers/index.rst index 6e9be1ca..cb86cf42 100644 --- a/docs/reference/markers/index.rst +++ b/docs/reference/markers/index.rst @@ -25,7 +25,7 @@ The following code example provides a shared event loop for all tests in `TestCl .. include:: class_scoped_loop_strict_mode_example.py :code: python -Requesting class scope with the test being part of a class will give a *UsageError*. +If you request class scope for a test that is not part of a class, it will result in a *UsageError*. Similar to class-scoped event loops, a module-scoped loop is provided when setting mark's scope to *module:* .. include:: module_scoped_loop_strict_mode_example.py From 746c11462e1c14f41146e9217ea43df99dc982c2 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Fri, 6 Dec 2024 12:35:29 -0500 Subject: [PATCH 151/226] Maintain contextvars.Context in fixtures and tests The approach I've taken here is to maintain a contextvars.Context instance in a contextvars.ContextVar, copying it from the ambient context whenever we create a new event loop. The fixture setup and teardown run within that context, and each test function gets a copy (as if it were created as a new asyncio.Task from within the fixture task). Fixes pytest-dev/pytest-asyncio#127. --- pytest_asyncio/plugin.py | 72 +++++++++++++++++-- .../test_async_fixtures_contextvars.py | 36 ++++++++++ 2 files changed, 101 insertions(+), 7 deletions(-) create mode 100644 tests/async_fixtures/test_async_fixtures_contextvars.py diff --git a/pytest_asyncio/plugin.py b/pytest_asyncio/plugin.py index d3e006d8..762c58ae 100644 --- a/pytest_asyncio/plugin.py +++ b/pytest_asyncio/plugin.py @@ -4,6 +4,7 @@ import asyncio import contextlib +import contextvars import enum import functools import inspect @@ -318,6 +319,8 @@ def _asyncgen_fixture_wrapper(request: FixtureRequest, **kwargs: Any): kwargs.pop(event_loop_fixture_id, None) gen_obj = func(**_add_kwargs(func, kwargs, event_loop, request)) + context = _event_loop_context.get(None) + async def setup(): res = await gen_obj.__anext__() # type: ignore[union-attr] return res @@ -335,9 +338,11 @@ async def async_finalizer() -> None: msg += "Yield only once." raise ValueError(msg) - event_loop.run_until_complete(async_finalizer()) + task = _create_task_in_context(event_loop, async_finalizer(), context) + event_loop.run_until_complete(task) - result = event_loop.run_until_complete(setup()) + setup_task = _create_task_in_context(event_loop, setup(), context) + result = event_loop.run_until_complete(setup_task) request.addfinalizer(finalizer) return result @@ -360,7 +365,10 @@ async def setup(): res = await func(**_add_kwargs(func, kwargs, event_loop, request)) return res - return event_loop.run_until_complete(setup()) + task = _create_task_in_context( + event_loop, setup(), _event_loop_context.get(None) + ) + return event_loop.run_until_complete(task) fixturedef.func = _async_fixture_wrapper # type: ignore[misc] @@ -584,6 +592,46 @@ def pytest_pycollect_makeitem_convert_async_functions_to_subclass( Session: "session", } +# _event_loop_context stores the Context in which asyncio tasks on the fixture +# event loop should be run. After fixture setup, individual async test functions +# are run on copies of this context. +_event_loop_context: contextvars.ContextVar[contextvars.Context] = ( + contextvars.ContextVar("pytest_asyncio_event_loop_context") +) + + +@contextlib.contextmanager +def _set_event_loop_context(): + """Set event_loop_context to a copy of the calling thread's current context.""" + context = contextvars.copy_context() + token = _event_loop_context.set(context) + try: + yield + finally: + _event_loop_context.reset(token) + + +def _create_task_in_context(loop, coro, context): + """ + Return an asyncio task that runs the coro in the specified context, + if possible. + + This allows fixture setup and teardown to be run as separate asyncio tasks, + while still being able to use context-manager idioms to maintain context + variables and make those variables visible to test functions. + + This is only fully supported on Python 3.11 and newer, as it requires + the API added for https://github.com/python/cpython/issues/91150. + On earlier versions, the returned task will use the default context instead. + """ + if context is not None: + try: + return loop.create_task(coro, context=context) + except TypeError: + pass + return loop.create_task(coro) + + # A stack used to push package-scoped loops during collection of a package # and pop those loops during collection of a Module __package_loop_stack: list[FixtureFunctionMarker | FixtureFunction] = [] @@ -631,7 +679,8 @@ def scoped_event_loop( loop = asyncio.new_event_loop() loop.__pytest_asyncio = True # type: ignore[attr-defined] asyncio.set_event_loop(loop) - yield loop + with _set_event_loop_context(): + yield loop loop.close() # @pytest.fixture does not register the fixture anywhere, so pytest doesn't @@ -938,9 +987,16 @@ def wrap_in_sync( @functools.wraps(func) def inner(*args, **kwargs): + # Give each test its own context based on the loop's main context. + context = _event_loop_context.get(None) + if context is not None: + # We are using our own event loop fixture, so make a new copy of the + # fixture context so that the test won't pollute it. + context = context.copy() + coro = func(*args, **kwargs) _loop = _get_event_loop_no_warn() - task = asyncio.ensure_future(coro, loop=_loop) + task = _create_task_in_context(_loop, coro, context) try: _loop.run_until_complete(task) except BaseException: @@ -1049,7 +1105,8 @@ def event_loop(request: FixtureRequest) -> Iterator[asyncio.AbstractEventLoop]: # 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 + with _set_event_loop_context(): + yield loop loop.close() @@ -1062,7 +1119,8 @@ def _session_event_loop( loop = asyncio.new_event_loop() loop.__pytest_asyncio = True # type: ignore[attr-defined] asyncio.set_event_loop(loop) - yield loop + with _set_event_loop_context(): + yield loop loop.close() diff --git a/tests/async_fixtures/test_async_fixtures_contextvars.py b/tests/async_fixtures/test_async_fixtures_contextvars.py new file mode 100644 index 00000000..25bb8106 --- /dev/null +++ b/tests/async_fixtures/test_async_fixtures_contextvars.py @@ -0,0 +1,36 @@ +""" +Regression test for https://github.com/pytest-dev/pytest-asyncio/issues/127: +contextvars were not properly maintained among fixtures and tests. +""" + +from __future__ import annotations + +import sys +from contextlib import asynccontextmanager +from contextvars import ContextVar + +import pytest + + +@asynccontextmanager +async def context_var_manager(): + context_var = ContextVar("context_var") + token = context_var.set("value") + try: + yield context_var + finally: + context_var.reset(token) + + +@pytest.fixture(scope="function") +async def context_var(): + async with context_var_manager() as v: + yield v + + +@pytest.mark.asyncio +@pytest.mark.xfail( + sys.version_info < (3, 11), reason="requires asyncio Task context support" +) +async def test(context_var): + assert context_var.get() == "value" From 3004bb76050593463819bb809249af76542e54ba Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Fri, 6 Dec 2024 23:26:38 -0500 Subject: [PATCH 152/226] Simplify contextvars support Instead of storing a Context in a context variable, just copy out the changes from the setup task's context into the ambient context, and reset the changes after running the finalizer task. --- pytest_asyncio/plugin.py | 115 ++++++++---------- .../test_async_fixtures_contextvars.py | 47 +++++-- 2 files changed, 88 insertions(+), 74 deletions(-) diff --git a/pytest_asyncio/plugin.py b/pytest_asyncio/plugin.py index 762c58ae..ac756a2a 100644 --- a/pytest_asyncio/plugin.py +++ b/pytest_asyncio/plugin.py @@ -319,12 +319,27 @@ def _asyncgen_fixture_wrapper(request: FixtureRequest, **kwargs: Any): kwargs.pop(event_loop_fixture_id, None) gen_obj = func(**_add_kwargs(func, kwargs, event_loop, request)) - context = _event_loop_context.get(None) - async def setup(): res = await gen_obj.__anext__() # type: ignore[union-attr] return res + context = contextvars.copy_context() + setup_task = _create_task_in_context(event_loop, setup(), context) + result = event_loop.run_until_complete(setup_task) + + # Copy the context vars set by the setup task back into the ambient + # context for the test. + context_tokens = [] + for var in context: + try: + if var.get() is context.get(var): + # Not modified by the fixture, so leave it as-is. + continue + except LookupError: + pass + token = var.set(context.get(var)) + context_tokens.append((var, token)) + def finalizer() -> None: """Yield again, to finalize.""" @@ -341,14 +356,39 @@ async def async_finalizer() -> None: task = _create_task_in_context(event_loop, async_finalizer(), context) event_loop.run_until_complete(task) - setup_task = _create_task_in_context(event_loop, setup(), context) - result = event_loop.run_until_complete(setup_task) + # Since the fixture is now complete, restore any context variables + # it had set back to their original values. + while context_tokens: + (var, token) = context_tokens.pop() + var.reset(token) + request.addfinalizer(finalizer) return result fixturedef.func = _asyncgen_fixture_wrapper # type: ignore[misc] +def _create_task_in_context(loop, coro, context): + """ + Return an asyncio task that runs the coro in the specified context, + if possible. + + This allows fixture setup and teardown to be run as separate asyncio tasks, + while still being able to use context-manager idioms to maintain context + variables and make those variables visible to test functions. + + This is only fully supported on Python 3.11 and newer, as it requires + the API added for https://github.com/python/cpython/issues/91150. + On earlier versions, the returned task will use the default context instead. + """ + if context is not None: + try: + return loop.create_task(coro, context=context) + except TypeError: + pass + return loop.create_task(coro) + + def _wrap_async_fixture(fixturedef: FixtureDef) -> None: fixture = fixturedef.func @@ -365,10 +405,11 @@ async def setup(): res = await func(**_add_kwargs(func, kwargs, event_loop, request)) return res - task = _create_task_in_context( - event_loop, setup(), _event_loop_context.get(None) - ) - return event_loop.run_until_complete(task) + # Since the fixture doesn't have a cleanup phase, if it set any context + # variables we don't have a good way to clear them again. + # Instead, treat this fixture like an asyncio.Task, which has its own + # independent Context that doesn't affect the caller. + return event_loop.run_until_complete(setup()) fixturedef.func = _async_fixture_wrapper # type: ignore[misc] @@ -592,46 +633,6 @@ def pytest_pycollect_makeitem_convert_async_functions_to_subclass( Session: "session", } -# _event_loop_context stores the Context in which asyncio tasks on the fixture -# event loop should be run. After fixture setup, individual async test functions -# are run on copies of this context. -_event_loop_context: contextvars.ContextVar[contextvars.Context] = ( - contextvars.ContextVar("pytest_asyncio_event_loop_context") -) - - -@contextlib.contextmanager -def _set_event_loop_context(): - """Set event_loop_context to a copy of the calling thread's current context.""" - context = contextvars.copy_context() - token = _event_loop_context.set(context) - try: - yield - finally: - _event_loop_context.reset(token) - - -def _create_task_in_context(loop, coro, context): - """ - Return an asyncio task that runs the coro in the specified context, - if possible. - - This allows fixture setup and teardown to be run as separate asyncio tasks, - while still being able to use context-manager idioms to maintain context - variables and make those variables visible to test functions. - - This is only fully supported on Python 3.11 and newer, as it requires - the API added for https://github.com/python/cpython/issues/91150. - On earlier versions, the returned task will use the default context instead. - """ - if context is not None: - try: - return loop.create_task(coro, context=context) - except TypeError: - pass - return loop.create_task(coro) - - # A stack used to push package-scoped loops during collection of a package # and pop those loops during collection of a Module __package_loop_stack: list[FixtureFunctionMarker | FixtureFunction] = [] @@ -679,8 +680,7 @@ def scoped_event_loop( loop = asyncio.new_event_loop() loop.__pytest_asyncio = True # type: ignore[attr-defined] asyncio.set_event_loop(loop) - with _set_event_loop_context(): - yield loop + yield loop loop.close() # @pytest.fixture does not register the fixture anywhere, so pytest doesn't @@ -987,16 +987,9 @@ def wrap_in_sync( @functools.wraps(func) def inner(*args, **kwargs): - # Give each test its own context based on the loop's main context. - context = _event_loop_context.get(None) - if context is not None: - # We are using our own event loop fixture, so make a new copy of the - # fixture context so that the test won't pollute it. - context = context.copy() - coro = func(*args, **kwargs) _loop = _get_event_loop_no_warn() - task = _create_task_in_context(_loop, coro, context) + task = asyncio.ensure_future(coro, loop=_loop) try: _loop.run_until_complete(task) except BaseException: @@ -1105,8 +1098,7 @@ def event_loop(request: FixtureRequest) -> Iterator[asyncio.AbstractEventLoop]: # 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] - with _set_event_loop_context(): - yield loop + yield loop loop.close() @@ -1119,8 +1111,7 @@ def _session_event_loop( loop = asyncio.new_event_loop() loop.__pytest_asyncio = True # type: ignore[attr-defined] asyncio.set_event_loop(loop) - with _set_event_loop_context(): - yield loop + yield loop loop.close() diff --git a/tests/async_fixtures/test_async_fixtures_contextvars.py b/tests/async_fixtures/test_async_fixtures_contextvars.py index 25bb8106..3f58be54 100644 --- a/tests/async_fixtures/test_async_fixtures_contextvars.py +++ b/tests/async_fixtures/test_async_fixtures_contextvars.py @@ -6,31 +6,54 @@ from __future__ import annotations import sys -from contextlib import asynccontextmanager +from contextlib import contextmanager from contextvars import ContextVar import pytest +_context_var = ContextVar("context_var") -@asynccontextmanager -async def context_var_manager(): - context_var = ContextVar("context_var") - token = context_var.set("value") + +@contextmanager +def context_var_manager(value): + token = _context_var.set(value) try: - yield context_var + yield finally: - context_var.reset(token) + _context_var.reset(token) + + +@pytest.fixture(scope="function") +async def no_var_fixture(): + with pytest.raises(LookupError): + _context_var.get() + yield + with pytest.raises(LookupError): + _context_var.get() + + +@pytest.fixture(scope="function") +async def var_fixture(no_var_fixture): + with context_var_manager("value"): + yield + + +@pytest.fixture(scope="function") +async def var_nop_fixture(var_fixture): + with context_var_manager(_context_var.get()): + yield @pytest.fixture(scope="function") -async def context_var(): - async with context_var_manager() as v: - yield v +def inner_var_fixture(var_nop_fixture): + assert _context_var.get() == "value" + with context_var_manager("value2"): + yield @pytest.mark.asyncio @pytest.mark.xfail( sys.version_info < (3, 11), reason="requires asyncio Task context support" ) -async def test(context_var): - assert context_var.get() == "value" +async def test(inner_var_fixture): + assert _context_var.get() == "value2" From 62ab185208b5c6d497c2618aae1bb96d6f3472f4 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Fri, 6 Dec 2024 23:38:57 -0500 Subject: [PATCH 153/226] Improve contextvars test coverage --- pytest_asyncio/plugin.py | 10 ++++----- .../test_async_fixtures_contextvars.py | 21 ++++++++++++------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/pytest_asyncio/plugin.py b/pytest_asyncio/plugin.py index ac756a2a..062437b7 100644 --- a/pytest_asyncio/plugin.py +++ b/pytest_asyncio/plugin.py @@ -381,12 +381,10 @@ def _create_task_in_context(loop, coro, context): the API added for https://github.com/python/cpython/issues/91150. On earlier versions, the returned task will use the default context instead. """ - if context is not None: - try: - return loop.create_task(coro, context=context) - except TypeError: - pass - return loop.create_task(coro) + try: + return loop.create_task(coro, context=context) + except TypeError: + return loop.create_task(coro) def _wrap_async_fixture(fixturedef: FixtureDef) -> None: diff --git a/tests/async_fixtures/test_async_fixtures_contextvars.py b/tests/async_fixtures/test_async_fixtures_contextvars.py index 3f58be54..bddab379 100644 --- a/tests/async_fixtures/test_async_fixtures_contextvars.py +++ b/tests/async_fixtures/test_async_fixtures_contextvars.py @@ -33,27 +33,34 @@ async def no_var_fixture(): @pytest.fixture(scope="function") -async def var_fixture(no_var_fixture): - with context_var_manager("value"): +async def var_fixture_1(no_var_fixture): + with context_var_manager("value1"): yield @pytest.fixture(scope="function") -async def var_nop_fixture(var_fixture): +async def var_nop_fixture(var_fixture_1): with context_var_manager(_context_var.get()): yield @pytest.fixture(scope="function") -def inner_var_fixture(var_nop_fixture): - assert _context_var.get() == "value" +def var_fixture_2(var_nop_fixture): + assert _context_var.get() == "value1" with context_var_manager("value2"): yield +@pytest.fixture(scope="function") +async def var_fixture_3(var_fixture_2): + assert _context_var.get() == "value2" + with context_var_manager("value3"): + yield + + @pytest.mark.asyncio @pytest.mark.xfail( sys.version_info < (3, 11), reason="requires asyncio Task context support" ) -async def test(inner_var_fixture): - assert _context_var.get() == "value2" +async def test(var_fixture_3): + assert _context_var.get() == "value3" From 97c682f48c60b60c07e977e6cd74e844d43ccd68 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Mon, 9 Dec 2024 09:37:46 -0500 Subject: [PATCH 154/226] Copy context variables from non-generator fixtures --- pytest_asyncio/plugin.py | 113 +++++++++++------- .../test_async_fixtures_contextvars.py | 11 +- 2 files changed, 80 insertions(+), 44 deletions(-) diff --git a/pytest_asyncio/plugin.py b/pytest_asyncio/plugin.py index 062437b7..e1ce5c9d 100644 --- a/pytest_asyncio/plugin.py +++ b/pytest_asyncio/plugin.py @@ -327,18 +327,7 @@ async def setup(): setup_task = _create_task_in_context(event_loop, setup(), context) result = event_loop.run_until_complete(setup_task) - # Copy the context vars set by the setup task back into the ambient - # context for the test. - context_tokens = [] - for var in context: - try: - if var.get() is context.get(var): - # Not modified by the fixture, so leave it as-is. - continue - except LookupError: - pass - token = var.set(context.get(var)) - context_tokens.append((var, token)) + reset_contextvars = _apply_contextvar_changes(context) def finalizer() -> None: """Yield again, to finalize.""" @@ -355,12 +344,8 @@ async def async_finalizer() -> None: task = _create_task_in_context(event_loop, async_finalizer(), context) event_loop.run_until_complete(task) - - # Since the fixture is now complete, restore any context variables - # it had set back to their original values. - while context_tokens: - (var, token) = context_tokens.pop() - var.reset(token) + if reset_contextvars is not None: + reset_contextvars() request.addfinalizer(finalizer) return result @@ -368,25 +353,6 @@ async def async_finalizer() -> None: fixturedef.func = _asyncgen_fixture_wrapper # type: ignore[misc] -def _create_task_in_context(loop, coro, context): - """ - Return an asyncio task that runs the coro in the specified context, - if possible. - - This allows fixture setup and teardown to be run as separate asyncio tasks, - while still being able to use context-manager idioms to maintain context - variables and make those variables visible to test functions. - - This is only fully supported on Python 3.11 and newer, as it requires - the API added for https://github.com/python/cpython/issues/91150. - On earlier versions, the returned task will use the default context instead. - """ - try: - return loop.create_task(coro, context=context) - except TypeError: - return loop.create_task(coro) - - def _wrap_async_fixture(fixturedef: FixtureDef) -> None: fixture = fixturedef.func @@ -403,11 +369,23 @@ async def setup(): res = await func(**_add_kwargs(func, kwargs, event_loop, request)) return res - # Since the fixture doesn't have a cleanup phase, if it set any context - # variables we don't have a good way to clear them again. - # Instead, treat this fixture like an asyncio.Task, which has its own - # independent Context that doesn't affect the caller. - return event_loop.run_until_complete(setup()) + context = contextvars.copy_context() + setup_task = _create_task_in_context(event_loop, setup(), context) + result = event_loop.run_until_complete(setup_task) + + # Copy the context vars modified by the setup task into the current + # context, and (if needed) add a finalizer to reset them. + # + # Note that this is slightly different from the behavior of a non-async + # fixture, which would rely on the fixture author to add a finalizer + # to reset the variables. In this case, the author of the fixture can't + # write such a finalizer because they have no way to capture the Context + # in which the setup function was run, so we need to do it for them. + reset_contextvars = _apply_contextvar_changes(context) + if reset_contextvars is not None: + request.addfinalizer(reset_contextvars) + + return result fixturedef.func = _async_fixture_wrapper # type: ignore[misc] @@ -432,6 +410,57 @@ def _get_event_loop_fixture_id_for_async_fixture( return event_loop_fixture_id +def _create_task_in_context(loop, coro, context): + """ + Return an asyncio task that runs the coro in the specified context, + if possible. + + This allows fixture setup and teardown to be run as separate asyncio tasks, + while still being able to use context-manager idioms to maintain context + variables and make those variables visible to test functions. + + This is only fully supported on Python 3.11 and newer, as it requires + the API added for https://github.com/python/cpython/issues/91150. + On earlier versions, the returned task will use the default context instead. + """ + try: + return loop.create_task(coro, context=context) + except TypeError: + return loop.create_task(coro) + + +def _apply_contextvar_changes( + context: contextvars.Context, +) -> Callable[[], None] | None: + """ + Copy contextvar changes from the given context to the current context. + + If any contextvars were modified by the fixture, return a finalizer that + will restore them. + """ + context_tokens = [] + for var in context: + try: + if var.get() is context.get(var): + # This variable is not modified, so leave it as-is. + continue + except LookupError: + # This variable isn't yet set in the current context at all. + pass + token = var.set(context.get(var)) + context_tokens.append((var, token)) + + if not context_tokens: + return None + + def restore_contextvars(): + while context_tokens: + (var, token) = context_tokens.pop() + var.reset(token) + + return restore_contextvars + + class PytestAsyncioFunction(Function): """Base class for all test functions managed by pytest-asyncio.""" diff --git a/tests/async_fixtures/test_async_fixtures_contextvars.py b/tests/async_fixtures/test_async_fixtures_contextvars.py index bddab379..8d67db49 100644 --- a/tests/async_fixtures/test_async_fixtures_contextvars.py +++ b/tests/async_fixtures/test_async_fixtures_contextvars.py @@ -58,9 +58,16 @@ async def var_fixture_3(var_fixture_2): yield +@pytest.fixture(scope="function") +async def var_fixture_4(var_fixture_3, request): + assert _context_var.get() == "value3" + _context_var.set("value4") + # Rely on fixture teardown to reset the context var. + + @pytest.mark.asyncio @pytest.mark.xfail( sys.version_info < (3, 11), reason="requires asyncio Task context support" ) -async def test(var_fixture_3): - assert _context_var.get() == "value3" +async def test(var_fixture_4): + assert _context_var.get() == "value4" From 0184cbab4766417aa662f8c7309bd9b8eb13d2ba Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Wed, 11 Dec 2024 09:51:09 -0500 Subject: [PATCH 155/226] Refactor tests to use Pytester Also add type annotations for _create_task_in_context. --- pytest_asyncio/plugin.py | 7 +- .../test_async_fixtures_contextvars.py | 264 +++++++++++++++--- 2 files changed, 225 insertions(+), 46 deletions(-) diff --git a/pytest_asyncio/plugin.py b/pytest_asyncio/plugin.py index e1ce5c9d..12ead10f 100644 --- a/pytest_asyncio/plugin.py +++ b/pytest_asyncio/plugin.py @@ -14,6 +14,7 @@ from collections.abc import ( AsyncIterator, Awaitable, + Coroutine as AbstractCoroutine, Generator, Iterable, Iterator, @@ -410,7 +411,11 @@ def _get_event_loop_fixture_id_for_async_fixture( return event_loop_fixture_id -def _create_task_in_context(loop, coro, context): +def _create_task_in_context( + loop: asyncio.AbstractEventLoop, + coro: AbstractCoroutine[Any, Any, _T], + context: contextvars.Context, +) -> asyncio.Task[_T]: """ Return an asyncio task that runs the coro in the specified context, if possible. diff --git a/tests/async_fixtures/test_async_fixtures_contextvars.py b/tests/async_fixtures/test_async_fixtures_contextvars.py index 8d67db49..ff79e17e 100644 --- a/tests/async_fixtures/test_async_fixtures_contextvars.py +++ b/tests/async_fixtures/test_async_fixtures_contextvars.py @@ -6,68 +6,242 @@ from __future__ import annotations import sys -from contextlib import contextmanager -from contextvars import ContextVar +from textwrap import dedent import pytest - -_context_var = ContextVar("context_var") +from pytest import Pytester + +_prelude = dedent( + """ + import pytest + import pytest_asyncio + from contextlib import contextmanager + from contextvars import ContextVar + + _context_var = ContextVar("context_var") + + @contextmanager + def context_var_manager(value): + token = _context_var.set(value) + try: + yield + finally: + _context_var.reset(token) +""" +) -@contextmanager -def context_var_manager(value): - token = _context_var.set(value) - try: - yield - finally: - _context_var.reset(token) +def test_var_from_sync_generator_propagates_to_async(pytester: Pytester): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") + pytester.makepyfile( + _prelude + + dedent( + """ + @pytest.fixture + def var_fixture(): + with context_var_manager("value"): + yield + @pytest_asyncio.fixture + async def check_var_fixture(var_fixture): + assert _context_var.get() == "value" -@pytest.fixture(scope="function") -async def no_var_fixture(): - with pytest.raises(LookupError): - _context_var.get() - yield - with pytest.raises(LookupError): - _context_var.get() + @pytest.mark.asyncio + async def test(check_var_fixture): + assert _context_var.get() == "value" + """ + ) + ) + result = pytester.runpytest("--asyncio-mode=strict") + result.assert_outcomes(passed=1) -@pytest.fixture(scope="function") -async def var_fixture_1(no_var_fixture): - with context_var_manager("value1"): - yield +@pytest.mark.xfail( + sys.version_info < (3, 11), + reason="requires asyncio Task context support", + strict=True, +) +def test_var_from_async_generator_propagates_to_sync(pytester: Pytester): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") + pytester.makepyfile( + _prelude + + dedent( + """ + @pytest_asyncio.fixture + async def var_fixture(): + with context_var_manager("value"): + yield + + @pytest.fixture + def check_var_fixture(var_fixture): + assert _context_var.get() == "value" + + @pytest.mark.asyncio + async def test(check_var_fixture): + assert _context_var.get() == "value" + """ + ) + ) + result = pytester.runpytest("--asyncio-mode=strict") + result.assert_outcomes(passed=1) -@pytest.fixture(scope="function") -async def var_nop_fixture(var_fixture_1): - with context_var_manager(_context_var.get()): - yield +@pytest.mark.xfail( + sys.version_info < (3, 11), + reason="requires asyncio Task context support", + strict=True, +) +def test_var_from_async_fixture_propagates_to_sync(pytester: Pytester): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") + pytester.makepyfile( + _prelude + + dedent( + """ + @pytest_asyncio.fixture + async def var_fixture(): + _context_var.set("value") + # Rely on async fixture teardown to reset the context var. + + @pytest.fixture + def check_var_fixture(var_fixture): + assert _context_var.get() == "value" + + def test(check_var_fixture): + assert _context_var.get() == "value" + """ + ) + ) + result = pytester.runpytest("--asyncio-mode=strict") + result.assert_outcomes(passed=1) -@pytest.fixture(scope="function") -def var_fixture_2(var_nop_fixture): - assert _context_var.get() == "value1" - with context_var_manager("value2"): - yield +@pytest.mark.xfail( + sys.version_info < (3, 11), + reason="requires asyncio Task context support", + strict=True, +) +def test_var_from_generator_reset_before_previous_fixture_cleanup(pytester: Pytester): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") + pytester.makepyfile( + _prelude + + dedent( + """ + @pytest_asyncio.fixture + async def no_var_fixture(): + with pytest.raises(LookupError): + _context_var.get() + yield + with pytest.raises(LookupError): + _context_var.get() + + @pytest_asyncio.fixture + async def var_fixture(no_var_fixture): + with context_var_manager("value"): + yield + + @pytest.mark.asyncio + async def test(var_fixture): + assert _context_var.get() == "value" + """ + ) + ) + result = pytester.runpytest("--asyncio-mode=strict") + result.assert_outcomes(passed=1) -@pytest.fixture(scope="function") -async def var_fixture_3(var_fixture_2): - assert _context_var.get() == "value2" - with context_var_manager("value3"): - yield +@pytest.mark.xfail( + sys.version_info < (3, 11), + reason="requires asyncio Task context support", + strict=True, +) +def test_var_from_fixture_reset_before_previous_fixture_cleanup(pytester: Pytester): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") + pytester.makepyfile( + _prelude + + dedent( + """ + @pytest_asyncio.fixture + async def no_var_fixture(): + with pytest.raises(LookupError): + _context_var.get() + yield + with pytest.raises(LookupError): + _context_var.get() + + @pytest_asyncio.fixture + async def var_fixture(no_var_fixture): + _context_var.set("value") + # Rely on async fixture teardown to reset the context var. + + @pytest.mark.asyncio + async def test(var_fixture): + assert _context_var.get() == "value" + """ + ) + ) + result = pytester.runpytest("--asyncio-mode=strict") + result.assert_outcomes(passed=1) -@pytest.fixture(scope="function") -async def var_fixture_4(var_fixture_3, request): - assert _context_var.get() == "value3" - _context_var.set("value4") - # Rely on fixture teardown to reset the context var. +@pytest.mark.xfail( + sys.version_info < (3, 11), + reason="requires asyncio Task context support", + strict=True, +) +def test_var_previous_value_restored_after_fixture(pytester: Pytester): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") + pytester.makepyfile( + _prelude + + dedent( + """ + @pytest_asyncio.fixture + async def var_fixture_1(): + with context_var_manager("value1"): + yield + assert _context_var.get() == "value1" + + @pytest_asyncio.fixture + async def var_fixture_2(var_fixture_1): + with context_var_manager("value2"): + yield + assert _context_var.get() == "value2" + + @pytest.mark.asyncio + async def test(var_fixture_2): + assert _context_var.get() == "value2" + """ + ) + ) + result = pytester.runpytest("--asyncio-mode=strict") + result.assert_outcomes(passed=1) -@pytest.mark.asyncio @pytest.mark.xfail( - sys.version_info < (3, 11), reason="requires asyncio Task context support" + sys.version_info < (3, 11), + reason="requires asyncio Task context support", + strict=True, ) -async def test(var_fixture_4): - assert _context_var.get() == "value4" +def test_var_set_to_existing_value_ok(pytester: Pytester): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") + pytester.makepyfile( + _prelude + + dedent( + """ + @pytest_asyncio.fixture + async def var_fixture(): + with context_var_manager("value"): + yield + + @pytest_asyncio.fixture + async def same_var_fixture(var_fixture): + with context_var_manager(_context_var.get()): + yield + + @pytest.mark.asyncio + async def test(same_var_fixture): + assert _context_var.get() == "value" + """ + ) + ) + result = pytester.runpytest("--asyncio-mode=strict") + result.assert_outcomes(passed=1) From f15b9c2469cacf7b2f2684b4abc2c121dd1defab Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Wed, 11 Dec 2024 10:04:48 -0500 Subject: [PATCH 156/226] Add release note for #1008 --- docs/reference/changelog.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/reference/changelog.rst b/docs/reference/changelog.rst index d29fa184..6f300ba7 100644 --- a/docs/reference/changelog.rst +++ b/docs/reference/changelog.rst @@ -7,6 +7,8 @@ Changelog - Deprecated: Added warning when asyncio test requests async ``@pytest.fixture`` in strict mode. This will become an error in a future version of flake8-asyncio. `#979 `_ - Updates the error message about `pytest.mark.asyncio`'s `scope` keyword argument to say `loop_scope` instead. `#1004 `_ - Verbose log displays correct parameter name: asyncio_default_fixture_loop_scope `#990 `_ +- Propagates `contextvars` set in async fixtures to other fixtures and tests on Python 3.11 and above. `#1008 `_ + 0.24.0 (2024-08-22) =================== From 9fd64da493b5278938ade7e1d73ee4a18543325a Mon Sep 17 00:00:00 2001 From: Robsdedude Date: Wed, 11 Dec 2024 13:29:54 +0100 Subject: [PATCH 157/226] changelog += `asyncio_default_fixture_loop_scope` This config option is arguably a new API surface, and it took me a fair bit of git archaeology to figure out from which version on I can use this config option. This entry might save some users some time in the future :) --- docs/reference/changelog.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/reference/changelog.rst b/docs/reference/changelog.rst index 6f300ba7..65e16717 100644 --- a/docs/reference/changelog.rst +++ b/docs/reference/changelog.rst @@ -10,6 +10,7 @@ Changelog - Propagates `contextvars` set in async fixtures to other fixtures and tests on Python 3.11 and above. `#1008 `_ + 0.24.0 (2024-08-22) =================== - BREAKING: Updated minimum supported pytest version to v8.2.0 @@ -17,6 +18,7 @@ Changelog - Deprecates the optional `scope` keyword argument to `pytest.mark.asyncio` for API consistency with ``pytest_asyncio.fixture``. Users are encouraged to use the `loop_scope` keyword argument, which does exactly the same. - Raises an error when passing `scope` or `loop_scope` as a positional argument to ``@pytest.mark.asyncio``. `#812 `_ - Fixes a bug that caused module-scoped async fixtures to fail when reused in other modules `#862 `_ `#668 `_ +- Added the ``asyncio_default_fixture_loop_scope`` configuration option `c74d1c3 `_ 0.23.8 (2024-07-17) From b24de088dbb92de2cedc506bcc4adb522a72bf7c Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Fri, 13 Dec 2024 06:51:16 +0100 Subject: [PATCH 158/226] build: Prepare release of v0.25.0 --- docs/reference/changelog.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference/changelog.rst b/docs/reference/changelog.rst index 65e16717..0b302d53 100644 --- a/docs/reference/changelog.rst +++ b/docs/reference/changelog.rst @@ -2,7 +2,7 @@ Changelog ========= -0.25.0 (UNRELEASED) +0.25.0 (2024-12-13) =================== - Deprecated: Added warning when asyncio test requests async ``@pytest.fixture`` in strict mode. This will become an error in a future version of flake8-asyncio. `#979 `_ - Updates the error message about `pytest.mark.asyncio`'s `scope` keyword argument to say `loop_scope` instead. `#1004 `_ From 8035fa0415256ac3df62d8fe152bf5a82fea4e86 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Dec 2024 18:26:07 +0000 Subject: [PATCH 159/226] Build(deps): Bump certifi in /dependencies/docs Bumps [certifi](https://github.com/certifi/python-certifi) from 2024.8.30 to 2024.12.14. - [Commits](https://github.com/certifi/python-certifi/compare/2024.08.30...2024.12.14) --- updated-dependencies: - dependency-name: certifi dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- dependencies/docs/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/docs/constraints.txt b/dependencies/docs/constraints.txt index d79e0456..b67acb85 100644 --- a/dependencies/docs/constraints.txt +++ b/dependencies/docs/constraints.txt @@ -1,6 +1,6 @@ alabaster==0.7.16 Babel==2.16.0 -certifi==2024.8.30 +certifi==2024.12.14 charset-normalizer==3.4.0 docutils==0.21.2 idna==3.10 From c44cc6827aa3281f20151d19f2e05da0a4bab695 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Dec 2024 18:05:33 +0000 Subject: [PATCH 160/226] Build(deps): Bump attrs from 24.2.0 to 24.3.0 in /dependencies/default Bumps [attrs](https://github.com/sponsors/hynek) from 24.2.0 to 24.3.0. - [Commits](https://github.com/sponsors/hynek/commits) --- updated-dependencies: - dependency-name: attrs dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index 9cd79a18..576acc5b 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -1,4 +1,4 @@ -attrs==24.2.0 +attrs==24.3.0 coverage==7.6.9 exceptiongroup==1.2.2 hypothesis==6.122.3 From 38ac4138428efc29923d50080364895c33d99b8d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 16 Dec 2024 22:58:35 +0000 Subject: [PATCH 161/226] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.8.2 → v0.8.3](https://github.com/astral-sh/ruff-pre-commit/compare/v0.8.2...v0.8.3) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index dc20cbd5..d91433d9 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,7 +6,7 @@ repos: - id: check-merge-conflict exclude: rst$ - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.8.2 + rev: v0.8.3 hooks: - id: ruff args: [--fix] From 7ce56e0a19be26cdfe084042848e61878b9d2da8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Dec 2024 18:37:16 +0000 Subject: [PATCH 162/226] Build(deps): Bump hypothesis in /dependencies/default Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.122.3 to 6.123.0. - [Release notes](https://github.com/HypothesisWorks/hypothesis/releases) - [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.122.3...hypothesis-python-6.123.0) --- updated-dependencies: - dependency-name: hypothesis dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index 576acc5b..a7e60fd4 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -1,7 +1,7 @@ attrs==24.3.0 coverage==7.6.9 exceptiongroup==1.2.2 -hypothesis==6.122.3 +hypothesis==6.123.0 iniconfig==2.0.0 packaging==24.2 pluggy==1.5.0 From 84eee346d1e7ef7ad1917906a76957c509809f46 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Dec 2024 18:34:13 +0000 Subject: [PATCH 163/226] Build(deps): Bump jinja2 from 3.1.4 to 3.1.5 in /dependencies/docs Bumps [jinja2](https://github.com/pallets/jinja) from 3.1.4 to 3.1.5. - [Release notes](https://github.com/pallets/jinja/releases) - [Changelog](https://github.com/pallets/jinja/blob/main/CHANGES.rst) - [Commits](https://github.com/pallets/jinja/compare/3.1.4...3.1.5) --- updated-dependencies: - dependency-name: jinja2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dependencies/docs/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/docs/constraints.txt b/dependencies/docs/constraints.txt index b67acb85..ed50f7ec 100644 --- a/dependencies/docs/constraints.txt +++ b/dependencies/docs/constraints.txt @@ -5,7 +5,7 @@ charset-normalizer==3.4.0 docutils==0.21.2 idna==3.10 imagesize==1.4.1 -Jinja2==3.1.4 +Jinja2==3.1.5 MarkupSafe==3.0.2 packaging==24.2 Pygments==2.18.0 From 065e7e397e8b3835f698280cfca4fa038898aee0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Dec 2024 18:34:10 +0000 Subject: [PATCH 164/226] Build(deps): Bump urllib3 from 2.2.3 to 2.3.0 in /dependencies/docs Bumps [urllib3](https://github.com/urllib3/urllib3) from 2.2.3 to 2.3.0. - [Release notes](https://github.com/urllib3/urllib3/releases) - [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst) - [Commits](https://github.com/urllib3/urllib3/compare/2.2.3...2.3.0) --- updated-dependencies: - dependency-name: urllib3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- dependencies/docs/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/docs/constraints.txt b/dependencies/docs/constraints.txt index ed50f7ec..aaf0a406 100644 --- a/dependencies/docs/constraints.txt +++ b/dependencies/docs/constraints.txt @@ -20,4 +20,4 @@ sphinxcontrib-jquery==4.1 sphinxcontrib-jsmath==1.0.1 sphinxcontrib-qthelp==2.0.0 sphinxcontrib-serializinghtml==2.0.0 -urllib3==2.2.3 +urllib3==2.3.0 From 581bd29b83fd063dcf6df3f7eb35b99211f7141f Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 23 Dec 2024 23:18:42 +0000 Subject: [PATCH 165/226] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.8.3 → v0.8.4](https://github.com/astral-sh/ruff-pre-commit/compare/v0.8.3...v0.8.4) - [github.com/pre-commit/mirrors-mypy: v1.13.0 → v1.14.0](https://github.com/pre-commit/mirrors-mypy/compare/v1.13.0...v1.14.0) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d91433d9..79249204 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,7 +6,7 @@ repos: - id: check-merge-conflict exclude: rst$ - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.8.3 + rev: v0.8.4 hooks: - id: ruff args: [--fix] @@ -42,7 +42,7 @@ repos: - id: check-yaml - id: debug-statements - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.13.0 + rev: v1.14.0 hooks: - id: mypy exclude: ^(docs|tests)/.* From c99fe570dbff94233efd2a3bb271f29d822371ff Mon Sep 17 00:00:00 2001 From: Fahrzin Hemmati Date: Mon, 23 Dec 2024 02:20:21 -0800 Subject: [PATCH 166/226] Check asyncio_mode (cheap) before _is_asyncio_fixture_function To fix https://github.com/pytest-dev/pytest-asyncio/issues/720 --- pytest_asyncio/plugin.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pytest_asyncio/plugin.py b/pytest_asyncio/plugin.py index 12ead10f..48e53271 100644 --- a/pytest_asyncio/plugin.py +++ b/pytest_asyncio/plugin.py @@ -239,7 +239,7 @@ def _preprocess_async_fixtures( func ): continue - if not _is_asyncio_fixture_function(func) and asyncio_mode == Mode.STRICT: + if asyncio_mode == Mode.STRICT and not _is_asyncio_fixture_function(func): # Ignore async fixtures without explicit asyncio mark in strict mode # This applies to pytest_trio fixtures, for example continue @@ -969,9 +969,9 @@ def pytest_pyfunc_call(pyfuncitem: Function) -> object | None: # fixturedefs. The last entry in the list is closest and the one used. func = fixtures[-1].func if ( - _is_coroutine_or_asyncgen(func) + asyncio_mode == Mode.STRICT + and _is_coroutine_or_asyncgen(func) and not _is_asyncio_fixture_function(func) - and asyncio_mode == Mode.STRICT ): warnings.warn( PytestDeprecationWarning( From f88ca4836daae406330bc02d3c3d7689425f9d16 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Dec 2024 18:19:29 +0000 Subject: [PATCH 167/226] Build(deps): Bump charset-normalizer in /dependencies/docs Bumps [charset-normalizer](https://github.com/jawah/charset_normalizer) from 3.4.0 to 3.4.1. - [Release notes](https://github.com/jawah/charset_normalizer/releases) - [Changelog](https://github.com/jawah/charset_normalizer/blob/master/CHANGELOG.md) - [Commits](https://github.com/jawah/charset_normalizer/compare/3.4.0...3.4.1) --- updated-dependencies: - dependency-name: charset-normalizer dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dependencies/docs/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/docs/constraints.txt b/dependencies/docs/constraints.txt index aaf0a406..530d174e 100644 --- a/dependencies/docs/constraints.txt +++ b/dependencies/docs/constraints.txt @@ -1,7 +1,7 @@ alabaster==0.7.16 Babel==2.16.0 certifi==2024.12.14 -charset-normalizer==3.4.0 +charset-normalizer==3.4.1 docutils==0.21.2 idna==3.10 imagesize==1.4.1 From 1a6d3bbd1ef07325b3d957c6c81f983e63725276 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Dec 2024 18:28:03 +0000 Subject: [PATCH 168/226] Build(deps): Bump coverage from 7.6.9 to 7.6.10 in /dependencies/default Bumps [coverage](https://github.com/nedbat/coveragepy) from 7.6.9 to 7.6.10. - [Release notes](https://github.com/nedbat/coveragepy/releases) - [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst) - [Commits](https://github.com/nedbat/coveragepy/compare/7.6.9...7.6.10) --- updated-dependencies: - dependency-name: coverage dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index a7e60fd4..7589439b 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -1,5 +1,5 @@ attrs==24.3.0 -coverage==7.6.9 +coverage==7.6.10 exceptiongroup==1.2.2 hypothesis==6.123.0 iniconfig==2.0.0 From bffed5d1d2755085420d5a2e226e1a50121a3a66 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Dec 2024 18:28:10 +0000 Subject: [PATCH 169/226] Build(deps): Bump hypothesis in /dependencies/default Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.123.0 to 6.123.2. - [Release notes](https://github.com/HypothesisWorks/hypothesis/releases) - [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.123.0...hypothesis-python-6.123.2) --- updated-dependencies: - dependency-name: hypothesis dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index 7589439b..934ec98c 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -1,7 +1,7 @@ attrs==24.3.0 coverage==7.6.10 exceptiongroup==1.2.2 -hypothesis==6.123.0 +hypothesis==6.123.2 iniconfig==2.0.0 packaging==24.2 pluggy==1.5.0 From 050a5f81c937f805d35d27f8871981e336ddeee0 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 30 Dec 2024 22:14:38 +0000 Subject: [PATCH 170/226] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/rhysd/actionlint: v1.7.4 → v1.7.5](https://github.com/rhysd/actionlint/compare/v1.7.4...v1.7.5) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 79249204..c79734ca 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -53,7 +53,7 @@ repos: hooks: - id: python-use-type-annotations - repo: https://github.com/rhysd/actionlint - rev: v1.7.4 + rev: v1.7.5 hooks: - id: actionlint-docker args: From 0642dcd27b35f5a74e385d4171893fe03d6edfcb Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Mon, 30 Dec 2024 20:02:36 +0100 Subject: [PATCH 171/226] fix: Fix broken event loop when a function-scoped test is in between two wider-scoped tests. The event_loop fixture finalizers only close event loops that were not created by pytest-asyncio. This prevents the finalizers from accidentally closing a module-scoped loop, for example. --- docs/reference/changelog.rst | 5 +++ pytest_asyncio/plugin.py | 48 +++++++++++++++------- tests/markers/test_mixed_scope.py | 36 ++++++++++++++++ tests/test_event_loop_fixture_finalizer.py | 3 +- 4 files changed, 76 insertions(+), 16 deletions(-) create mode 100644 tests/markers/test_mixed_scope.py diff --git a/docs/reference/changelog.rst b/docs/reference/changelog.rst index 0b302d53..e219b723 100644 --- a/docs/reference/changelog.rst +++ b/docs/reference/changelog.rst @@ -2,6 +2,11 @@ Changelog ========= +0.25.1 (UNRELEASED) +=================== +- Fixes an issue that caused a broken event loop when a function-scoped test was executed in between two tests with wider loop scope `#950 `_ + + 0.25.0 (2024-12-13) =================== - Deprecated: Added warning when asyncio test requests async ``@pytest.fixture`` in strict mode. This will become an error in a future version of flake8-asyncio. `#979 `_ diff --git a/pytest_asyncio/plugin.py b/pytest_asyncio/plugin.py index 48e53271..aaaa9af3 100644 --- a/pytest_asyncio/plugin.py +++ b/pytest_asyncio/plugin.py @@ -10,7 +10,7 @@ import inspect import socket import warnings -from asyncio import AbstractEventLoopPolicy +from asyncio import AbstractEventLoop, AbstractEventLoopPolicy from collections.abc import ( AsyncIterator, Awaitable, @@ -762,6 +762,19 @@ def _temporary_event_loop_policy(policy: AbstractEventLoopPolicy) -> Iterator[No try: yield finally: + # Try detecting user-created event loops that were left unclosed + # at the end of a test. + try: + current_loop: AbstractEventLoop | None = _get_event_loop_no_warn() + except RuntimeError: + current_loop = None + if current_loop is not None and not current_loop.is_closed(): + warnings.warn( + _UNCLOSED_EVENT_LOOP_WARNING % current_loop, + DeprecationWarning, + ) + current_loop.close() + asyncio.set_event_loop_policy(old_loop_policy) # When a test uses both a scoped event loop and the event_loop fixture, # the "_provide_clean_event_loop" finalizer of the event_loop fixture @@ -906,7 +919,7 @@ def _close_event_loop() -> None: loop = policy.get_event_loop() except RuntimeError: loop = None - if loop is not None: + if loop is not None and not getattr(loop, "__pytest_asyncio", False): if not loop.is_closed(): warnings.warn( _UNCLOSED_EVENT_LOOP_WARNING % loop, @@ -923,7 +936,7 @@ def _restore_policy(): loop = _get_event_loop_no_warn(previous_policy) except RuntimeError: loop = None - if loop: + if loop and not getattr(loop, "__pytest_asyncio", False): loop.close() asyncio.set_event_loop_policy(previous_policy) @@ -938,8 +951,13 @@ def _provide_clean_event_loop() -> None: # Note that we cannot set the loop to None, because get_event_loop only creates # a new loop, when set_event_loop has not been called. policy = asyncio.get_event_loop_policy() - new_loop = policy.new_event_loop() - policy.set_event_loop(new_loop) + try: + old_loop = _get_event_loop_no_warn(policy) + except RuntimeError: + old_loop = None + if old_loop is not None and not getattr(old_loop, "__pytest_asyncio", False): + new_loop = policy.new_event_loop() + policy.set_event_loop(new_loop) def _get_event_loop_no_warn( @@ -1122,16 +1140,16 @@ def _retrieve_scope_root(item: Collector | Item, scope: str) -> Collector: def event_loop(request: FixtureRequest) -> Iterator[asyncio.AbstractEventLoop]: """Create an instance of the default event loop for each test case.""" new_loop_policy = request.getfixturevalue(event_loop_policy.__name__) - asyncio.set_event_loop_policy(new_loop_policy) - 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() + with _temporary_event_loop_policy(new_loop_policy): + 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() @pytest.fixture(scope="session") diff --git a/tests/markers/test_mixed_scope.py b/tests/markers/test_mixed_scope.py new file mode 100644 index 00000000..40eaaa35 --- /dev/null +++ b/tests/markers/test_mixed_scope.py @@ -0,0 +1,36 @@ +from __future__ import annotations + +from textwrap import dedent + +from pytest import Pytester + + +def test_function_scoped_loop_restores_previous_loop_scope(pytester: Pytester): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") + pytester.makepyfile( + dedent( + """\ + import asyncio + import pytest + + + module_loop: asyncio.AbstractEventLoop + + @pytest.mark.asyncio(loop_scope="module") + async def test_remember_loop(): + global module_loop + module_loop = asyncio.get_running_loop() + + @pytest.mark.asyncio(loop_scope="function") + async def test_with_function_scoped_loop(): + pass + + @pytest.mark.asyncio(loop_scope="module") + async def test_runs_in_same_loop(): + global module_loop + assert asyncio.get_running_loop() is module_loop + """ + ) + ) + result = pytester.runpytest("--asyncio-mode=strict") + result.assert_outcomes(passed=3) diff --git a/tests/test_event_loop_fixture_finalizer.py b/tests/test_event_loop_fixture_finalizer.py index 17cc85b9..1e378643 100644 --- a/tests/test_event_loop_fixture_finalizer.py +++ b/tests/test_event_loop_fixture_finalizer.py @@ -14,7 +14,8 @@ def test_event_loop_fixture_finalizer_returns_fresh_loop_after_test(pytester: Py import pytest - loop = asyncio.get_event_loop_policy().get_event_loop() + loop = asyncio.new_event_loop() + asyncio.set_event_loop(loop) @pytest.mark.asyncio async def test_1(): From 0c931b7eab4d9e9c8a53c0e1c632628161413034 Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Mon, 30 Dec 2024 20:16:43 +0100 Subject: [PATCH 172/226] refactor: Extracted function to check if a loop was created by pytest-asyncio. --- pytest_asyncio/plugin.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/pytest_asyncio/plugin.py b/pytest_asyncio/plugin.py index aaaa9af3..2de7ac97 100644 --- a/pytest_asyncio/plugin.py +++ b/pytest_asyncio/plugin.py @@ -872,8 +872,7 @@ def pytest_fixture_setup( policy = asyncio.get_event_loop_policy() try: old_loop = _get_event_loop_no_warn(policy) - is_pytest_asyncio_loop = getattr(old_loop, "__pytest_asyncio", False) - if old_loop is not loop and not is_pytest_asyncio_loop: + if old_loop is not loop and not _is_pytest_asyncio_loop(old_loop): old_loop.close() except RuntimeError: # Either the current event loop has been set to None @@ -886,6 +885,10 @@ def pytest_fixture_setup( yield +def _is_pytest_asyncio_loop(loop: AbstractEventLoop) -> bool: + return getattr(loop, "__pytest_asyncio", False) + + def _add_finalizers(fixturedef: FixtureDef, *finalizers: Callable[[], object]) -> None: """ Registers the specified fixture finalizers in the fixture. @@ -919,7 +922,7 @@ def _close_event_loop() -> None: loop = policy.get_event_loop() except RuntimeError: loop = None - if loop is not None and not getattr(loop, "__pytest_asyncio", False): + if loop is not None and not _is_pytest_asyncio_loop(loop): if not loop.is_closed(): warnings.warn( _UNCLOSED_EVENT_LOOP_WARNING % loop, @@ -936,7 +939,7 @@ def _restore_policy(): loop = _get_event_loop_no_warn(previous_policy) except RuntimeError: loop = None - if loop and not getattr(loop, "__pytest_asyncio", False): + if loop and not _is_pytest_asyncio_loop(loop): loop.close() asyncio.set_event_loop_policy(previous_policy) @@ -955,7 +958,7 @@ def _provide_clean_event_loop() -> None: old_loop = _get_event_loop_no_warn(policy) except RuntimeError: old_loop = None - if old_loop is not None and not getattr(old_loop, "__pytest_asyncio", False): + if old_loop is not None and not _is_pytest_asyncio_loop(old_loop): new_loop = policy.new_event_loop() policy.set_event_loop(new_loop) From dafef6c65b4b9dd90fac62e60e43629e3f881d0d Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Mon, 30 Dec 2024 20:20:39 +0100 Subject: [PATCH 173/226] refactor: Extracted a function to mark an event loop as created by pytest-asyncio. --- pytest_asyncio/plugin.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/pytest_asyncio/plugin.py b/pytest_asyncio/plugin.py index 2de7ac97..8b8401c6 100644 --- a/pytest_asyncio/plugin.py +++ b/pytest_asyncio/plugin.py @@ -709,8 +709,7 @@ def scoped_event_loop( ) -> Iterator[asyncio.AbstractEventLoop]: new_loop_policy = event_loop_policy with _temporary_event_loop_policy(new_loop_policy): - loop = asyncio.new_event_loop() - loop.__pytest_asyncio = True # type: ignore[attr-defined] + loop = _make_pytest_asyncio_loop(asyncio.new_event_loop()) asyncio.set_event_loop(loop) yield loop loop.close() @@ -885,6 +884,11 @@ def pytest_fixture_setup( yield +def _make_pytest_asyncio_loop(loop: AbstractEventLoop) -> AbstractEventLoop: + loop.__pytest_asyncio = True # type: ignore[attr-defined] + return loop + + def _is_pytest_asyncio_loop(loop: AbstractEventLoop) -> bool: return getattr(loop, "__pytest_asyncio", False) @@ -1161,8 +1165,7 @@ def _session_event_loop( ) -> Iterator[asyncio.AbstractEventLoop]: new_loop_policy = event_loop_policy with _temporary_event_loop_policy(new_loop_policy): - loop = asyncio.new_event_loop() - loop.__pytest_asyncio = True # type: ignore[attr-defined] + loop = _make_pytest_asyncio_loop(asyncio.new_event_loop()) asyncio.set_event_loop(loop) yield loop loop.close() From 04f90445e10568df4d47812541798cdb62259154 Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Mon, 30 Dec 2024 20:24:13 +0100 Subject: [PATCH 174/226] refactor: Replace the "__original_fixture_loop" magic attribute with the more generic "__pytest_asyncio" magic attribute. --- pytest_asyncio/plugin.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pytest_asyncio/plugin.py b/pytest_asyncio/plugin.py index 8b8401c6..2956f58e 100644 --- a/pytest_asyncio/plugin.py +++ b/pytest_asyncio/plugin.py @@ -861,7 +861,7 @@ def pytest_fixture_setup( # 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): + if not _is_pytest_asyncio_loop(loop): _, fixture_line_number = inspect.getsourcelines(fixturedef.func) warnings.warn( _REDEFINED_EVENT_LOOP_FIXTURE_WARNING @@ -1154,7 +1154,7 @@ def event_loop(request: FixtureRequest) -> Iterator[asyncio.AbstractEventLoop]: # 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] + loop = _make_pytest_asyncio_loop(loop) yield loop loop.close() From a4e82ab25b9d6238c46e078313402584d65e11c9 Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Tue, 31 Dec 2024 06:46:37 +0100 Subject: [PATCH 175/226] docs: Added changelog entry for #1020. --- docs/reference/changelog.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/reference/changelog.rst b/docs/reference/changelog.rst index e219b723..e5fa25d6 100644 --- a/docs/reference/changelog.rst +++ b/docs/reference/changelog.rst @@ -5,6 +5,7 @@ Changelog 0.25.1 (UNRELEASED) =================== - Fixes an issue that caused a broken event loop when a function-scoped test was executed in between two tests with wider loop scope `#950 `_ +- Improves test collection speed in auto mode `#1020 `_ 0.25.0 (2024-12-13) From 2fd10f824302d45da752341c60c8ddec48297a1b Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Tue, 31 Dec 2024 07:55:23 +0100 Subject: [PATCH 176/226] docs: Clarify deprecation of event_loop fixture. --- docs/reference/fixtures/index.rst | 9 +++++++++ docs/reference/markers/index.rst | 2 ++ 2 files changed, 11 insertions(+) diff --git a/docs/reference/fixtures/index.rst b/docs/reference/fixtures/index.rst index 37eec503..280e62ec 100644 --- a/docs/reference/fixtures/index.rst +++ b/docs/reference/fixtures/index.rst @@ -4,6 +4,13 @@ Fixtures event_loop ========== +*This fixture is deprecated.* + +*If you want to request an asyncio event loop with a scope other than function +scope, use the "loop_scope" argument to* :ref:`reference/markers/asyncio` *when marking the tests. +If you want to return different types of event loops, use the* :ref:`reference/fixtures/event_loop_policy` +*fixture.* + Creates a new asyncio event loop based on the current event loop policy. The new loop is available as the return value of this fixture for synchronous functions, or via `asyncio.get_running_loop `__ for asynchronous functions. The event loop is closed when the fixture scope ends. @@ -20,6 +27,8 @@ If you need to change the type of the event loop, prefer setting a custom event If the ``pytest.mark.asyncio`` decorator is applied to a test function, the ``event_loop`` fixture will be requested automatically by the test function. +.. _reference/fixtures/event_loop_policy: + event_loop_policy ================= Returns the event loop policy used to create asyncio event loops. diff --git a/docs/reference/markers/index.rst b/docs/reference/markers/index.rst index cb86cf42..e7d700c9 100644 --- a/docs/reference/markers/index.rst +++ b/docs/reference/markers/index.rst @@ -2,6 +2,8 @@ Markers ======= +.. _reference/markers/asyncio: + ``pytest.mark.asyncio`` ======================= A coroutine or async generator with this marker is treated as a test function by pytest. From 41c645b3b79709c2812a3aa3b17943074bc33f48 Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Tue, 31 Dec 2024 07:59:21 +0100 Subject: [PATCH 177/226] fix: Correct warning message when redefining the event_loop fixture. The message new refers to the "loop_scope" keyword argument, rather than "scope". --- docs/reference/changelog.rst | 1 + pytest_asyncio/plugin.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/reference/changelog.rst b/docs/reference/changelog.rst index e5fa25d6..61e34d49 100644 --- a/docs/reference/changelog.rst +++ b/docs/reference/changelog.rst @@ -6,6 +6,7 @@ Changelog =================== - Fixes an issue that caused a broken event loop when a function-scoped test was executed in between two tests with wider loop scope `#950 `_ - Improves test collection speed in auto mode `#1020 `_ +- Corrects the warning that is emitted upon redefining the event_loop fixture 0.25.0 (2024-12-13) diff --git a/pytest_asyncio/plugin.py b/pytest_asyncio/plugin.py index 2956f58e..8ad17c0a 100644 --- a/pytest_asyncio/plugin.py +++ b/pytest_asyncio/plugin.py @@ -794,7 +794,7 @@ def _temporary_event_loop_policy(policy: AbstractEventLoopPolicy) -> Iterator[No Replacing the event_loop fixture with a custom implementation is deprecated and will lead to errors in the future. If you want to request an asyncio event loop with a scope other than function - scope, use the "scope" argument to the asyncio mark when marking the tests. + scope, use the "loop_scope" argument to the asyncio mark when marking the tests. If you want to return different types of event loops, use the event_loop_policy fixture. """ From c236550e739b55ee62f3e6ec7f71b4f4231236d1 Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Tue, 31 Dec 2024 08:01:38 +0100 Subject: [PATCH 178/226] docs: Fix broken link to the pytest.mark.asyncio reference. --- docs/reference/fixtures/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference/fixtures/index.rst b/docs/reference/fixtures/index.rst index 280e62ec..04953783 100644 --- a/docs/reference/fixtures/index.rst +++ b/docs/reference/fixtures/index.rst @@ -19,7 +19,7 @@ The fixture scope defaults to ``function`` scope. .. include:: event_loop_example.py :code: python -Note that, when using the ``event_loop`` fixture, you need to interact with the event loop using methods like ``event_loop.run_until_complete``. If you want to *await* code inside your test function, you need to write a coroutine and use it as a test function. The `asyncio <#pytest-mark-asyncio>`__ marker +Note that, when using the ``event_loop`` fixture, you need to interact with the event loop using methods like ``event_loop.run_until_complete``. If you want to *await* code inside your test function, you need to write a coroutine and use it as a test function. The :ref:`asyncio ` marker is used to mark coroutines that should be treated as test functions. If you need to change the type of the event loop, prefer setting a custom event loop policy over redefining the ``event_loop`` fixture. From 623ab74b80b6f748e88254714f9b21a16eb7911e Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Thu, 2 Jan 2025 05:58:42 +0100 Subject: [PATCH 179/226] docs: Prepare release of v0.25.1. --- docs/reference/changelog.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference/changelog.rst b/docs/reference/changelog.rst index 61e34d49..aca0ea0f 100644 --- a/docs/reference/changelog.rst +++ b/docs/reference/changelog.rst @@ -2,7 +2,7 @@ Changelog ========= -0.25.1 (UNRELEASED) +0.25.1 (2025-01-02) =================== - Fixes an issue that caused a broken event loop when a function-scoped test was executed in between two tests with wider loop scope `#950 `_ - Improves test collection speed in auto mode `#1020 `_ From 941e8b5104d86bb1b06b15fd3395f23120203c09 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Jan 2025 18:26:54 +0000 Subject: [PATCH 180/226] Build(deps): Bump pygments from 2.18.0 to 2.19.1 in /dependencies/docs Bumps [pygments](https://github.com/pygments/pygments) from 2.18.0 to 2.19.1. - [Release notes](https://github.com/pygments/pygments/releases) - [Changelog](https://github.com/pygments/pygments/blob/master/CHANGES) - [Commits](https://github.com/pygments/pygments/compare/2.18.0...2.19.1) --- updated-dependencies: - dependency-name: pygments dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- dependencies/docs/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/docs/constraints.txt b/dependencies/docs/constraints.txt index 530d174e..607c1632 100644 --- a/dependencies/docs/constraints.txt +++ b/dependencies/docs/constraints.txt @@ -8,7 +8,7 @@ imagesize==1.4.1 Jinja2==3.1.5 MarkupSafe==3.0.2 packaging==24.2 -Pygments==2.18.0 +Pygments==2.19.1 requests==2.32.3 snowballstemmer==2.2.0 Sphinx==8.0.2 From aae43d4f766dfd8f9a643faad41be411888a5d16 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Jan 2025 18:05:44 +0000 Subject: [PATCH 181/226] Build(deps): Bump hypothesis in /dependencies/default Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.123.2 to 6.123.4. - [Release notes](https://github.com/HypothesisWorks/hypothesis/releases) - [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.123.2...hypothesis-python-6.123.4) --- updated-dependencies: - dependency-name: hypothesis dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index 934ec98c..816c4639 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -1,7 +1,7 @@ attrs==24.3.0 coverage==7.6.10 exceptiongroup==1.2.2 -hypothesis==6.123.2 +hypothesis==6.123.4 iniconfig==2.0.0 packaging==24.2 pluggy==1.5.0 From e8ffb10528aaf578dc9ccc7ddbb1fadab56be8ac Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 7 Jan 2025 00:27:18 +0000 Subject: [PATCH 182/226] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.8.4 → v0.8.6](https://github.com/astral-sh/ruff-pre-commit/compare/v0.8.4...v0.8.6) - [github.com/pre-commit/mirrors-mypy: v1.14.0 → v1.14.1](https://github.com/pre-commit/mirrors-mypy/compare/v1.14.0...v1.14.1) - [github.com/rhysd/actionlint: v1.7.5 → v1.7.6](https://github.com/rhysd/actionlint/compare/v1.7.5...v1.7.6) --- .pre-commit-config.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c79734ca..c1943f60 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,7 +6,7 @@ repos: - id: check-merge-conflict exclude: rst$ - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.8.4 + rev: v0.8.6 hooks: - id: ruff args: [--fix] @@ -42,7 +42,7 @@ repos: - id: check-yaml - id: debug-statements - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.14.0 + rev: v1.14.1 hooks: - id: mypy exclude: ^(docs|tests)/.* @@ -53,7 +53,7 @@ repos: hooks: - id: python-use-type-annotations - repo: https://github.com/rhysd/actionlint - rev: v1.7.5 + rev: v1.7.6 hooks: - id: actionlint-docker args: From c3ad6340b8ad251f3c03d6bbe399f08434059bda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Janek=20Nouvertn=C3=A9?= <25355197+provinzkraut@users.noreply.github.com> Date: Sun, 5 Jan 2025 14:04:36 +0100 Subject: [PATCH 183/226] fix: Shutdown generators before closing event loops. Add a comment --- docs/reference/changelog.rst | 5 ++++ pytest_asyncio/plugin.py | 39 ++++++++++++++++++++------------ tests/test_event_loop_fixture.py | 27 ++++++++++++++++++++++ 3 files changed, 56 insertions(+), 15 deletions(-) diff --git a/docs/reference/changelog.rst b/docs/reference/changelog.rst index aca0ea0f..dfd3ee9a 100644 --- a/docs/reference/changelog.rst +++ b/docs/reference/changelog.rst @@ -2,6 +2,11 @@ Changelog ========= +0.25.2 (UNRELEASED) +=================== + +- Call ``loop.shutdown_asyncgens()`` before closing the event loop to ensure async generators are closed in the same manner as ``asyncio.run`` does `#1034 `_ + 0.25.1 (2025-01-02) =================== - Fixes an issue that caused a broken event loop when a function-scoped test was executed in between two tests with wider loop scope `#950 `_ diff --git a/pytest_asyncio/plugin.py b/pytest_asyncio/plugin.py index 8ad17c0a..2f028ae1 100644 --- a/pytest_asyncio/plugin.py +++ b/pytest_asyncio/plugin.py @@ -708,11 +708,12 @@ def scoped_event_loop( event_loop_policy, ) -> Iterator[asyncio.AbstractEventLoop]: new_loop_policy = event_loop_policy - with _temporary_event_loop_policy(new_loop_policy): - loop = _make_pytest_asyncio_loop(asyncio.new_event_loop()) + with ( + _temporary_event_loop_policy(new_loop_policy), + _provide_event_loop() as loop, + ): asyncio.set_event_loop(loop) yield loop - loop.close() # @pytest.fixture does not register the fixture anywhere, so pytest doesn't # know it exists. We work around this by attaching the fixture function to the @@ -1147,16 +1148,26 @@ def _retrieve_scope_root(item: Collector | Item, scope: str) -> Collector: def event_loop(request: FixtureRequest) -> Iterator[asyncio.AbstractEventLoop]: """Create an instance of the default event loop for each test case.""" new_loop_policy = request.getfixturevalue(event_loop_policy.__name__) - with _temporary_event_loop_policy(new_loop_policy): - 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 = _make_pytest_asyncio_loop(loop) + with _temporary_event_loop_policy(new_loop_policy), _provide_event_loop() as loop: yield loop - loop.close() + + +@contextlib.contextmanager +def _provide_event_loop() -> Iterator[asyncio.AbstractEventLoop]: + 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 = _make_pytest_asyncio_loop(loop) + try: + yield loop + finally: + try: + loop.run_until_complete(loop.shutdown_asyncgens()) + finally: + loop.close() @pytest.fixture(scope="session") @@ -1164,11 +1175,9 @@ def _session_event_loop( request: FixtureRequest, event_loop_policy: AbstractEventLoopPolicy ) -> Iterator[asyncio.AbstractEventLoop]: new_loop_policy = event_loop_policy - with _temporary_event_loop_policy(new_loop_policy): - loop = _make_pytest_asyncio_loop(asyncio.new_event_loop()) + with _temporary_event_loop_policy(new_loop_policy), _provide_event_loop() as loop: asyncio.set_event_loop(loop) yield loop - loop.close() @pytest.fixture(scope="session", autouse=True) diff --git a/tests/test_event_loop_fixture.py b/tests/test_event_loop_fixture.py index 21785075..447d15d5 100644 --- a/tests/test_event_loop_fixture.py +++ b/tests/test_event_loop_fixture.py @@ -53,3 +53,30 @@ async def test_custom_policy_is_not_overwritten(): ) result = pytester.runpytest_subprocess("--asyncio-mode=strict") result.assert_outcomes(passed=2) + + +def test_event_loop_fixture_handles_unclosed_async_gen( + pytester: Pytester, +): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") + pytester.makepyfile( + dedent( + """\ + import asyncio + import pytest + + pytest_plugins = 'pytest_asyncio' + + @pytest.mark.asyncio + async def test_something(): + async def generator_fn(): + yield + yield + + gen = generator_fn() + await gen.__anext__() + """ + ) + ) + result = pytester.runpytest_subprocess("--asyncio-mode=strict", "-W", "default") + result.assert_outcomes(passed=1, warnings=0) From 2188cdbbf7b47e653957d3f39aeb7d4d0de80bf4 Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Wed, 8 Jan 2025 07:05:05 +0100 Subject: [PATCH 184/226] build: Prepare release of v0.25.2. --- docs/reference/changelog.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference/changelog.rst b/docs/reference/changelog.rst index dfd3ee9a..a28c9fd3 100644 --- a/docs/reference/changelog.rst +++ b/docs/reference/changelog.rst @@ -2,7 +2,7 @@ Changelog ========= -0.25.2 (UNRELEASED) +0.25.2 (2025-01-08) =================== - Call ``loop.shutdown_asyncgens()`` before closing the event loop to ensure async generators are closed in the same manner as ``asyncio.run`` does `#1034 `_ From b3283ea689785a01d24b75c387f637695be14861 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Jan 2025 18:37:16 +0000 Subject: [PATCH 185/226] Build(deps): Bump hypothesis in /dependencies/default Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.123.4 to 6.123.16. - [Release notes](https://github.com/HypothesisWorks/hypothesis/releases) - [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.123.4...hypothesis-python-6.123.16) --- updated-dependencies: - dependency-name: hypothesis dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index 816c4639..91f889b0 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -1,7 +1,7 @@ attrs==24.3.0 coverage==7.6.10 exceptiongroup==1.2.2 -hypothesis==6.123.4 +hypothesis==6.123.16 iniconfig==2.0.0 packaging==24.2 pluggy==1.5.0 From 84609be0a9fa8dce8d903794ddc6f66c1e4e7534 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 13 Jan 2025 23:05:19 +0000 Subject: [PATCH 186/226] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.8.6 → v0.9.1](https://github.com/astral-sh/ruff-pre-commit/compare/v0.8.6...v0.9.1) - [github.com/sirosen/check-jsonschema: 0.30.0 → 0.31.0](https://github.com/sirosen/check-jsonschema/compare/0.30.0...0.31.0) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c1943f60..49613c4e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,7 +6,7 @@ repos: - id: check-merge-conflict exclude: rst$ - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.8.6 + rev: v0.9.1 hooks: - id: ruff args: [--fix] @@ -65,7 +65,7 @@ repos: - 'SC1004:' stages: [manual] - repo: https://github.com/sirosen/check-jsonschema - rev: 0.30.0 + rev: 0.31.0 hooks: - id: check-github-actions - repo: https://github.com/tox-dev/pyproject-fmt From 5a0c567a5227730937f0f75977b4dfbcdd741c4c Mon Sep 17 00:00:00 2001 From: Maciej Nowak Date: Mon, 6 Jan 2025 12:42:53 +0100 Subject: [PATCH 187/226] feat: Configuration option for setting default loop_scope for tests New configuration option, asyncio_default_test_loop_scope, provides default value for loop_scope argument of asyncio marker. This can be used to use the same event loop in auto mode without need to use modifyitems hook. Test functions can still override loop_scope by using asyncio marker. --- .../change_default_test_loop.rst | 24 ++++++ docs/how-to-guides/index.rst | 2 +- .../run_session_tests_in_same_loop.rst | 10 --- .../session_scoped_loop_example.py | 10 --- .../test_session_scoped_loop_example.py | 63 --------------- docs/reference/changelog.rst | 6 +- docs/reference/configuration.rst | 6 ++ pytest_asyncio/plugin.py | 34 ++++++-- tests/test_asyncio_mark.py | 77 +++++++++++++++++++ 9 files changed, 141 insertions(+), 91 deletions(-) create mode 100644 docs/how-to-guides/change_default_test_loop.rst delete mode 100644 docs/how-to-guides/run_session_tests_in_same_loop.rst delete mode 100644 docs/how-to-guides/session_scoped_loop_example.py delete mode 100644 docs/how-to-guides/test_session_scoped_loop_example.py diff --git a/docs/how-to-guides/change_default_test_loop.rst b/docs/how-to-guides/change_default_test_loop.rst new file mode 100644 index 00000000..c5b625d1 --- /dev/null +++ b/docs/how-to-guides/change_default_test_loop.rst @@ -0,0 +1,24 @@ +======================================================= +How to change the default event loop scope of all tests +======================================================= +The :ref:`configuration/asyncio_default_test_loop_scope` configuration option sets the default event loop scope for asynchronous tests. The following code snippets configure all tests to run in a session-scoped loop by default: + +.. code-block:: ini + :caption: pytest.ini + + [pytest] + asyncio_default_test_loop_scope = session + +.. code-block:: toml + :caption: pyproject.toml + + [tool.pytest.ini_options] + asyncio_default_test_loop_scope = "session" + +.. code-block:: ini + :caption: setup.cfg + + [tool:pytest] + asyncio_default_test_loop_scope = session + +Please refer to :ref:`configuration/asyncio_default_test_loop_scope` for other valid scopes. diff --git a/docs/how-to-guides/index.rst b/docs/how-to-guides/index.rst index 7b3c4f31..04276256 100644 --- a/docs/how-to-guides/index.rst +++ b/docs/how-to-guides/index.rst @@ -9,10 +9,10 @@ How-To Guides migrate_from_0_23 change_fixture_loop change_default_fixture_loop + change_default_test_loop run_class_tests_in_same_loop run_module_tests_in_same_loop run_package_tests_in_same_loop - run_session_tests_in_same_loop multiple_loops uvloop test_item_is_async diff --git a/docs/how-to-guides/run_session_tests_in_same_loop.rst b/docs/how-to-guides/run_session_tests_in_same_loop.rst deleted file mode 100644 index f166fea0..00000000 --- a/docs/how-to-guides/run_session_tests_in_same_loop.rst +++ /dev/null @@ -1,10 +0,0 @@ -========================================================== -How to run all tests in the session in the same event loop -========================================================== -All tests can be run inside the same event loop by marking them with ``pytest.mark.asyncio(loop_scope="session")``. -The easiest way to mark all tests is via a ``pytest_collection_modifyitems`` hook in the ``conftest.py`` at the root folder of your test suite. - -.. include:: session_scoped_loop_example.py - :code: python - -Note that this will also override *all* manually applied marks in *strict* mode. diff --git a/docs/how-to-guides/session_scoped_loop_example.py b/docs/how-to-guides/session_scoped_loop_example.py deleted file mode 100644 index 79cc8676..00000000 --- a/docs/how-to-guides/session_scoped_loop_example.py +++ /dev/null @@ -1,10 +0,0 @@ -import pytest - -from pytest_asyncio import is_async_test - - -def pytest_collection_modifyitems(items): - pytest_asyncio_tests = (item for item in items if is_async_test(item)) - session_scope_marker = pytest.mark.asyncio(loop_scope="session") - for async_test in pytest_asyncio_tests: - async_test.add_marker(session_scope_marker, append=False) diff --git a/docs/how-to-guides/test_session_scoped_loop_example.py b/docs/how-to-guides/test_session_scoped_loop_example.py deleted file mode 100644 index 3d642246..00000000 --- a/docs/how-to-guides/test_session_scoped_loop_example.py +++ /dev/null @@ -1,63 +0,0 @@ -from pathlib import Path -from textwrap import dedent - -from pytest import Pytester - - -def test_session_scoped_loop_configuration_works_in_auto_mode( - pytester: Pytester, -): - session_wide_mark_conftest = ( - Path(__file__).parent / "session_scoped_loop_example.py" - ) - pytester.makeconftest(session_wide_mark_conftest.read_text()) - pytester.makepyfile( - dedent( - """\ - import asyncio - - session_loop = None - - async def test_store_loop(request): - global session_loop - session_loop = asyncio.get_running_loop() - - async def test_compare_loop(request): - global session_loop - assert asyncio.get_running_loop() is session_loop - """ - ) - ) - result = pytester.runpytest_subprocess("--asyncio-mode=auto") - result.assert_outcomes(passed=2) - - -def test_session_scoped_loop_configuration_works_in_strict_mode( - pytester: Pytester, -): - session_wide_mark_conftest = ( - Path(__file__).parent / "session_scoped_loop_example.py" - ) - pytester.makeconftest(session_wide_mark_conftest.read_text()) - pytester.makepyfile( - dedent( - """\ - import asyncio - import pytest - - session_loop = None - - @pytest.mark.asyncio - async def test_store_loop(request): - global session_loop - session_loop = asyncio.get_running_loop() - - @pytest.mark.asyncio - async def test_compare_loop(request): - global session_loop - assert asyncio.get_running_loop() is session_loop - """ - ) - ) - result = pytester.runpytest_subprocess("--asyncio-mode=strict") - result.assert_outcomes(passed=2) diff --git a/docs/reference/changelog.rst b/docs/reference/changelog.rst index a28c9fd3..11b3d811 100644 --- a/docs/reference/changelog.rst +++ b/docs/reference/changelog.rst @@ -2,9 +2,13 @@ Changelog ========= -0.25.2 (2025-01-08) +0.26.0 (UNRELEASED) =================== +- Adds configuration option that sets default event loop scope for all testss `#793 `_ + +0.25.2 (2025-01-08) +=================== - Call ``loop.shutdown_asyncgens()`` before closing the event loop to ensure async generators are closed in the same manner as ``asyncio.run`` does `#1034 `_ 0.25.1 (2025-01-02) diff --git a/docs/reference/configuration.rst b/docs/reference/configuration.rst index 35c67302..81175549 100644 --- a/docs/reference/configuration.rst +++ b/docs/reference/configuration.rst @@ -8,6 +8,12 @@ asyncio_default_fixture_loop_scope ================================== Determines the default event loop scope of asynchronous fixtures. When this configuration option is unset, it defaults to the fixture scope. In future versions of pytest-asyncio, the value will default to ``function`` when unset. Possible values are: ``function``, ``class``, ``module``, ``package``, ``session`` +.. _configuration/asyncio_default_test_loop_scope: + +asyncio_default_test_loop_scope +=============================== +Determines the default event loop scope of asynchronous tests. When this configuration option is unset, it default to function scope. Possible values are: ``function``, ``class``, ``module``, ``package``, ``session`` + asyncio_mode ============ The pytest-asyncio mode can be set by the ``asyncio_mode`` configuration option in the `configuration file diff --git a/pytest_asyncio/plugin.py b/pytest_asyncio/plugin.py index 2f028ae1..8f6d91dc 100644 --- a/pytest_asyncio/plugin.py +++ b/pytest_asyncio/plugin.py @@ -107,6 +107,12 @@ def pytest_addoption(parser: Parser, pluginmanager: PytestPluginManager) -> None help="default scope of the asyncio event loop used to execute async fixtures", default=None, ) + parser.addini( + "asyncio_default_test_loop_scope", + type="string", + help="default scope of the asyncio event loop used to execute tests", + default="function", + ) @overload @@ -217,9 +223,15 @@ def pytest_configure(config: Config) -> None: def pytest_report_header(config: Config) -> list[str]: """Add asyncio config to pytest header.""" mode = _get_asyncio_mode(config) - default_loop_scope = config.getini("asyncio_default_fixture_loop_scope") + default_fixture_loop_scope = config.getini("asyncio_default_fixture_loop_scope") + default_test_loop_scope = _get_default_test_loop_scope(config) + header = [ + f"mode={mode}", + f"asyncio_default_fixture_loop_scope={default_fixture_loop_scope}", + f"asyncio_default_test_loop_scope={default_test_loop_scope}", + ] return [ - f"asyncio: mode={mode}, asyncio_default_fixture_loop_scope={default_loop_scope}" + "asyncio: " + ", ".join(header), ] @@ -807,7 +819,8 @@ def pytest_generate_tests(metafunc: Metafunc) -> None: marker = metafunc.definition.get_closest_marker("asyncio") if not marker: return - scope = _get_marked_loop_scope(marker) + default_loop_scope = _get_default_test_loop_scope(metafunc.config) + scope = _get_marked_loop_scope(marker, default_loop_scope) if scope == "function": return event_loop_node = _retrieve_scope_root(metafunc.definition, scope) @@ -1078,7 +1091,8 @@ def pytest_runtest_setup(item: pytest.Item) -> None: marker = item.get_closest_marker("asyncio") if marker is None: return - scope = _get_marked_loop_scope(marker) + default_loop_scope = _get_default_test_loop_scope(item.config) + scope = _get_marked_loop_scope(marker, default_loop_scope) if scope != "function": parent_node = _retrieve_scope_root(item, scope) event_loop_fixture_id = parent_node.stash[_event_loop_fixture_id] @@ -1108,7 +1122,9 @@ def pytest_runtest_setup(item: pytest.Item) -> None: """ -def _get_marked_loop_scope(asyncio_marker: Mark) -> _ScopeName: +def _get_marked_loop_scope( + asyncio_marker: Mark, default_loop_scope: _ScopeName +) -> _ScopeName: assert asyncio_marker.name == "asyncio" if asyncio_marker.args or ( asyncio_marker.kwargs and set(asyncio_marker.kwargs) - {"loop_scope", "scope"} @@ -1119,12 +1135,18 @@ def _get_marked_loop_scope(asyncio_marker: Mark) -> _ScopeName: raise pytest.UsageError(_DUPLICATE_LOOP_SCOPE_DEFINITION_ERROR) warnings.warn(PytestDeprecationWarning(_MARKER_SCOPE_KWARG_DEPRECATION_WARNING)) scope = asyncio_marker.kwargs.get("loop_scope") or asyncio_marker.kwargs.get( - "scope", "function" + "scope" ) + if scope is None: + scope = default_loop_scope assert scope in {"function", "class", "module", "package", "session"} return scope +def _get_default_test_loop_scope(config: Config) -> _ScopeName: + return config.getini("asyncio_default_test_loop_scope") + + def _retrieve_scope_root(item: Collector | Item, scope: str) -> Collector: node_type_by_scope = { "class": Class, diff --git a/tests/test_asyncio_mark.py b/tests/test_asyncio_mark.py index e22be989..81731adb 100644 --- a/tests/test_asyncio_mark.py +++ b/tests/test_asyncio_mark.py @@ -146,3 +146,80 @@ async def test_a(): result.stdout.fnmatch_lines( ["*Tests based on asynchronous generators are not supported*"] ) + + +def test_asyncio_marker_fallbacks_to_configured_default_loop_scope_if_not_set( + pytester: Pytester, +): + pytester.makeini( + dedent( + """\ + [pytest] + asyncio_default_fixture_loop_scope = function + asyncio_default_test_loop_scope = session + """ + ) + ) + + pytester.makepyfile( + dedent( + """\ + import asyncio + import pytest_asyncio + import pytest + + loop: asyncio.AbstractEventLoop + + @pytest_asyncio.fixture(loop_scope="session", scope="session") + async def session_loop_fixture(): + global loop + loop = asyncio.get_running_loop() + + async def test_a(session_loop_fixture): + global loop + assert asyncio.get_running_loop() is loop + """ + ) + ) + + result = pytester.runpytest("--asyncio-mode=auto") + result.assert_outcomes(passed=1) + + +def test_asyncio_marker_uses_marker_loop_scope_even_if_config_is_set( + pytester: Pytester, +): + pytester.makeini( + dedent( + """\ + [pytest] + asyncio_default_fixture_loop_scope = function + asyncio_default_test_loop_scope = module + """ + ) + ) + + pytester.makepyfile( + dedent( + """\ + import asyncio + import pytest_asyncio + import pytest + + loop: asyncio.AbstractEventLoop + + @pytest_asyncio.fixture(loop_scope="session", scope="session") + async def session_loop_fixture(): + global loop + loop = asyncio.get_running_loop() + + @pytest.mark.asyncio(loop_scope="session") + async def test_a(session_loop_fixture): + global loop + assert asyncio.get_running_loop() is loop + """ + ) + ) + + result = pytester.runpytest("--asyncio-mode=auto") + result.assert_outcomes(passed=1) From 97d1f8d5df18fda103914b255bf21936ee2ce825 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 20 Jan 2025 23:00:36 +0000 Subject: [PATCH 188/226] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.9.1 → v0.9.2](https://github.com/astral-sh/ruff-pre-commit/compare/v0.9.1...v0.9.2) - [github.com/rhysd/actionlint: v1.7.6 → v1.7.7](https://github.com/rhysd/actionlint/compare/v1.7.6...v1.7.7) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 49613c4e..1f4fb790 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,7 +6,7 @@ repos: - id: check-merge-conflict exclude: rst$ - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.9.1 + rev: v0.9.2 hooks: - id: ruff args: [--fix] @@ -53,7 +53,7 @@ repos: hooks: - id: python-use-type-annotations - repo: https://github.com/rhysd/actionlint - rev: v1.7.6 + rev: v1.7.7 hooks: - id: actionlint-docker args: From dc3e2475b0630407b28bac876ff4d4eab165b507 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Jan 2025 18:04:11 +0000 Subject: [PATCH 189/226] Build(deps): Bump hypothesis in /dependencies/default Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.123.16 to 6.124.1. - [Release notes](https://github.com/HypothesisWorks/hypothesis/releases) - [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.123.16...hypothesis-python-6.124.1) --- updated-dependencies: - dependency-name: hypothesis dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index 91f889b0..67646449 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -1,7 +1,7 @@ attrs==24.3.0 coverage==7.6.10 exceptiongroup==1.2.2 -hypothesis==6.123.16 +hypothesis==6.124.1 iniconfig==2.0.0 packaging==24.2 pluggy==1.5.0 From c0120b5ee670da80703b7170c5d823ca70307647 Mon Sep 17 00:00:00 2001 From: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Date: Sat, 18 Jan 2025 16:31:58 +0100 Subject: [PATCH 190/226] Fix FixtureFunction TypeAlias and TypeVars --- pytest_asyncio/plugin.py | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/pytest_asyncio/plugin.py b/pytest_asyncio/plugin.py index 8f6d91dc..dbd0e91f 100644 --- a/pytest_asyncio/plugin.py +++ b/pytest_asyncio/plugin.py @@ -56,14 +56,18 @@ _ScopeName = Literal["session", "package", "module", "class", "function"] _T = TypeVar("_T") -SimpleFixtureFunction = TypeVar( - "SimpleFixtureFunction", bound=Callable[..., Awaitable[object]] +FixtureFunctionT = TypeVar( + "FixtureFunctionT", + bound=Union[Callable[..., Awaitable[Any]], Callable[..., AsyncIterator[Any]]], ) -FactoryFixtureFunction = TypeVar( - "FactoryFixtureFunction", bound=Callable[..., AsyncIterator[object]] +FixtureFunctionU = TypeVar( + "FixtureFunctionU", + bound=Union[Callable[..., Awaitable[Any]], Callable[..., AsyncIterator[Any]]], ) -FixtureFunction = Union[SimpleFixtureFunction, FactoryFixtureFunction] -FixtureFunctionMarker = Callable[[FixtureFunction], FixtureFunction] +FixtureFunctionType = Union[ + Callable[..., Awaitable[Any]], Callable[..., AsyncIterator[Any]] +] +FixtureFunctionMarker = Callable[[FixtureFunctionT], FixtureFunctionT] class PytestAsyncioError(Exception): @@ -117,7 +121,7 @@ def pytest_addoption(parser: Parser, pluginmanager: PytestPluginManager) -> None @overload def fixture( - fixture_function: FixtureFunction, + fixture_function: FixtureFunctionT, *, scope: _ScopeName | Callable[[str, Config], _ScopeName] = ..., loop_scope: _ScopeName | None = ..., @@ -129,7 +133,7 @@ def fixture( | None ) = ..., name: str | None = ..., -) -> FixtureFunction: ... +) -> FixtureFunctionT: ... @overload @@ -146,14 +150,14 @@ def fixture( | None ) = ..., name: str | None = None, -) -> FixtureFunctionMarker: ... +) -> FixtureFunctionMarker[FixtureFunctionU]: ... def fixture( - fixture_function: FixtureFunction | None = None, + fixture_function: FixtureFunctionT | None = None, loop_scope: _ScopeName | None = None, **kwargs: Any, -) -> FixtureFunction | FixtureFunctionMarker: +) -> FixtureFunctionT | FixtureFunctionMarker[FixtureFunctionU]: if fixture_function is not None: _make_asyncio_fixture_function(fixture_function, loop_scope) return pytest.fixture(fixture_function, **kwargs) @@ -161,7 +165,7 @@ def fixture( else: @functools.wraps(fixture) - def inner(fixture_function: FixtureFunction) -> FixtureFunction: + def inner(fixture_function: FixtureFunctionU) -> FixtureFunctionU: return fixture(fixture_function, loop_scope=loop_scope, **kwargs) return inner @@ -679,7 +683,9 @@ def pytest_pycollect_makeitem_convert_async_functions_to_subclass( # A stack used to push package-scoped loops during collection of a package # and pop those loops during collection of a Module -__package_loop_stack: list[FixtureFunctionMarker | FixtureFunction] = [] +__package_loop_stack: list[ + FixtureFunctionMarker[FixtureFunctionType] | FixtureFunctionType +] = [] @pytest.hookimpl From b9c65d2d781b61048a81d4aada8d0aba8ef2bae2 Mon Sep 17 00:00:00 2001 From: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Date: Sat, 18 Jan 2025 16:46:57 +0100 Subject: [PATCH 191/226] Fix __package_loop_stack --- pytest_asyncio/plugin.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pytest_asyncio/plugin.py b/pytest_asyncio/plugin.py index dbd0e91f..95d01fe8 100644 --- a/pytest_asyncio/plugin.py +++ b/pytest_asyncio/plugin.py @@ -683,9 +683,7 @@ def pytest_pycollect_makeitem_convert_async_functions_to_subclass( # A stack used to push package-scoped loops during collection of a package # and pop those loops during collection of a Module -__package_loop_stack: list[ - FixtureFunctionMarker[FixtureFunctionType] | FixtureFunctionType -] = [] +__package_loop_stack: list[Callable[..., Any]] = [] @pytest.hookimpl From 6ddb6f1b1ac860a3816ede6250caeacd39ac1eff Mon Sep 17 00:00:00 2001 From: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Date: Tue, 21 Jan 2025 11:41:01 +0100 Subject: [PATCH 192/226] Simplify and improve typing even further --- pyproject.toml | 1 + pytest_asyncio/plugin.py | 38 +++++++++++++++++++------------------- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index b89c24da..c503970e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -38,6 +38,7 @@ dynamic = [ dependencies = [ "pytest>=8.2,<9", + "typing-extensions>=4.12; python_version<'3.10'", ] optional-dependencies.docs = [ "sphinx>=5.3", diff --git a/pytest_asyncio/plugin.py b/pytest_asyncio/plugin.py index 95d01fe8..2ec504ff 100644 --- a/pytest_asyncio/plugin.py +++ b/pytest_asyncio/plugin.py @@ -9,6 +9,7 @@ import functools import inspect import socket +import sys import warnings from asyncio import AbstractEventLoop, AbstractEventLoopPolicy from collections.abc import ( @@ -53,21 +54,17 @@ StashKey, ) +if sys.version_info >= (3, 10): + from typing import ParamSpec +else: + from typing_extensions import ParamSpec + + _ScopeName = Literal["session", "package", "module", "class", "function"] _T = TypeVar("_T") - -FixtureFunctionT = TypeVar( - "FixtureFunctionT", - bound=Union[Callable[..., Awaitable[Any]], Callable[..., AsyncIterator[Any]]], -) -FixtureFunctionU = TypeVar( - "FixtureFunctionU", - bound=Union[Callable[..., Awaitable[Any]], Callable[..., AsyncIterator[Any]]], -) -FixtureFunctionType = Union[ - Callable[..., Awaitable[Any]], Callable[..., AsyncIterator[Any]] -] -FixtureFunctionMarker = Callable[[FixtureFunctionT], FixtureFunctionT] +_R = TypeVar("_R", bound=Union[Awaitable[Any], AsyncIterator[Any]]) +_P = ParamSpec("_P") +FixtureFunction = Callable[_P, _R] class PytestAsyncioError(Exception): @@ -121,7 +118,7 @@ def pytest_addoption(parser: Parser, pluginmanager: PytestPluginManager) -> None @overload def fixture( - fixture_function: FixtureFunctionT, + fixture_function: FixtureFunction[_P, _R], *, scope: _ScopeName | Callable[[str, Config], _ScopeName] = ..., loop_scope: _ScopeName | None = ..., @@ -133,7 +130,7 @@ def fixture( | None ) = ..., name: str | None = ..., -) -> FixtureFunctionT: ... +) -> FixtureFunction[_P, _R]: ... @overload @@ -150,14 +147,17 @@ def fixture( | None ) = ..., name: str | None = None, -) -> FixtureFunctionMarker[FixtureFunctionU]: ... +) -> Callable[[FixtureFunction[_P, _R]], FixtureFunction[_P, _R]]: ... def fixture( - fixture_function: FixtureFunctionT | None = None, + fixture_function: FixtureFunction[_P, _R] | None = None, loop_scope: _ScopeName | None = None, **kwargs: Any, -) -> FixtureFunctionT | FixtureFunctionMarker[FixtureFunctionU]: +) -> ( + FixtureFunction[_P, _R] + | Callable[[FixtureFunction[_P, _R]], FixtureFunction[_P, _R]] +): if fixture_function is not None: _make_asyncio_fixture_function(fixture_function, loop_scope) return pytest.fixture(fixture_function, **kwargs) @@ -165,7 +165,7 @@ def fixture( else: @functools.wraps(fixture) - def inner(fixture_function: FixtureFunctionU) -> FixtureFunctionU: + def inner(fixture_function: FixtureFunction[_P, _R]) -> FixtureFunction[_P, _R]: return fixture(fixture_function, loop_scope=loop_scope, **kwargs) return inner From 320555536223e4a24c4960246ef2873bd57676fb Mon Sep 17 00:00:00 2001 From: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Date: Tue, 21 Jan 2025 12:49:10 +0100 Subject: [PATCH 193/226] Add changelog entries --- docs/reference/changelog.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/reference/changelog.rst b/docs/reference/changelog.rst index 11b3d811..4897188c 100644 --- a/docs/reference/changelog.rst +++ b/docs/reference/changelog.rst @@ -5,6 +5,8 @@ Changelog 0.26.0 (UNRELEASED) =================== - Adds configuration option that sets default event loop scope for all testss `#793 `_ +- Improved type annotations for ``pytest_asyncio.fixture`` `#1045 `_ +- Added ``typing-extensions`` as additional dependency for Python ``<3.10`` `#1045 `_ 0.25.2 (2025-01-08) From fe32d2d81f9b1bc041376a5f31248a964cf110b4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 Jan 2025 18:35:20 +0000 Subject: [PATCH 194/226] Build(deps): Bump pypa/gh-action-pypi-publish from 1.12.3 to 1.12.4 Bumps [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) from 1.12.3 to 1.12.4. - [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases) - [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/v1.12.3...v1.12.4) --- updated-dependencies: - dependency-name: pypa/gh-action-pypi-publish dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 12348ae1..e12ad385 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -151,7 +151,7 @@ jobs: run: | pandoc -s -o README.md README.rst - name: PyPI upload - uses: pypa/gh-action-pypi-publish@v1.12.3 + uses: pypa/gh-action-pypi-publish@v1.12.4 with: attestations: true packages-dir: dist From 92b006faf065a655a59fff8eabf7087a25ba1af0 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 27 Jan 2025 23:08:02 +0000 Subject: [PATCH 195/226] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.9.2 → v0.9.3](https://github.com/astral-sh/ruff-pre-commit/compare/v0.9.2...v0.9.3) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1f4fb790..8410474e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,7 +6,7 @@ repos: - id: check-merge-conflict exclude: rst$ - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.9.2 + rev: v0.9.3 hooks: - id: ruff args: [--fix] From e8de4dc37a707be7d040609c47ec477bab681f29 Mon Sep 17 00:00:00 2001 From: Min RK Date: Mon, 27 Jan 2025 14:53:37 +0100 Subject: [PATCH 196/226] fix: Avoid errors in cleanup of async generators when event loop is already closed check `is_closed()` before calling cleanup methods and degrade exceptions to warnings during cleanup to avoid problems --- docs/reference/changelog.rst | 7 +++- pytest_asyncio/plugin.py | 12 ++++--- tests/test_event_loop_fixture.py | 58 ++++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+), 5 deletions(-) diff --git a/docs/reference/changelog.rst b/docs/reference/changelog.rst index 4897188c..92e61835 100644 --- a/docs/reference/changelog.rst +++ b/docs/reference/changelog.rst @@ -9,10 +9,16 @@ Changelog - Added ``typing-extensions`` as additional dependency for Python ``<3.10`` `#1045 `_ +0.25.3 (2025-01-28) +=================== +- Avoid errors in cleanup of async generators when event loop is already closed `#1040 `_ + + 0.25.2 (2025-01-08) =================== - Call ``loop.shutdown_asyncgens()`` before closing the event loop to ensure async generators are closed in the same manner as ``asyncio.run`` does `#1034 `_ + 0.25.1 (2025-01-02) =================== - Fixes an issue that caused a broken event loop when a function-scoped test was executed in between two tests with wider loop scope `#950 `_ @@ -28,7 +34,6 @@ Changelog - Propagates `contextvars` set in async fixtures to other fixtures and tests on Python 3.11 and above. `#1008 `_ - 0.24.0 (2024-08-22) =================== - BREAKING: Updated minimum supported pytest version to v8.2.0 diff --git a/pytest_asyncio/plugin.py b/pytest_asyncio/plugin.py index 2ec504ff..8a1d8733 100644 --- a/pytest_asyncio/plugin.py +++ b/pytest_asyncio/plugin.py @@ -1190,10 +1190,14 @@ def _provide_event_loop() -> Iterator[asyncio.AbstractEventLoop]: try: yield loop finally: - try: - loop.run_until_complete(loop.shutdown_asyncgens()) - finally: - loop.close() + # cleanup the event loop if it hasn't been cleaned up already + if not loop.is_closed(): + try: + loop.run_until_complete(loop.shutdown_asyncgens()) + except Exception as e: + warnings.warn(f"Error cleaning up asyncio loop: {e}", RuntimeWarning) + finally: + loop.close() @pytest.fixture(scope="session") diff --git a/tests/test_event_loop_fixture.py b/tests/test_event_loop_fixture.py index 447d15d5..5417a14d 100644 --- a/tests/test_event_loop_fixture.py +++ b/tests/test_event_loop_fixture.py @@ -80,3 +80,61 @@ async def generator_fn(): ) result = pytester.runpytest_subprocess("--asyncio-mode=strict", "-W", "default") result.assert_outcomes(passed=1, warnings=0) + + +def test_event_loop_already_closed( + pytester: Pytester, +): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") + pytester.makepyfile( + dedent( + """\ + import asyncio + import pytest + import pytest_asyncio + pytest_plugins = 'pytest_asyncio' + + @pytest_asyncio.fixture + async def _event_loop(): + return asyncio.get_running_loop() + + @pytest.fixture + def cleanup_after(_event_loop): + yield + # fixture has its own cleanup code + _event_loop.close() + + @pytest.mark.asyncio + async def test_something(cleanup_after): + await asyncio.sleep(0.01) + """ + ) + ) + result = pytester.runpytest_subprocess("--asyncio-mode=strict", "-W", "default") + result.assert_outcomes(passed=1, warnings=0) + + +def test_event_loop_fixture_asyncgen_error( + pytester: Pytester, +): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") + pytester.makepyfile( + dedent( + """\ + import asyncio + import pytest + + pytest_plugins = 'pytest_asyncio' + + @pytest.mark.asyncio + async def test_something(): + # mock shutdown_asyncgen failure + loop = asyncio.get_running_loop() + async def fail(): + raise RuntimeError("mock error cleaning up...") + loop.shutdown_asyncgens = fail + """ + ) + ) + result = pytester.runpytest_subprocess("--asyncio-mode=strict", "-W", "default") + result.assert_outcomes(passed=1, warnings=1) From 6da8c87ee8745eb1bcd158548c33c251dffaf568 Mon Sep 17 00:00:00 2001 From: Min RK Date: Mon, 27 Jan 2025 14:53:37 +0100 Subject: [PATCH 197/226] docs: Fixed typo in changelog. --- docs/reference/changelog.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference/changelog.rst b/docs/reference/changelog.rst index 92e61835..dd703fa1 100644 --- a/docs/reference/changelog.rst +++ b/docs/reference/changelog.rst @@ -4,7 +4,7 @@ Changelog 0.26.0 (UNRELEASED) =================== -- Adds configuration option that sets default event loop scope for all testss `#793 `_ +- Adds configuration option that sets default event loop scope for all tests `#793 `_ - Improved type annotations for ``pytest_asyncio.fixture`` `#1045 `_ - Added ``typing-extensions`` as additional dependency for Python ``<3.10`` `#1045 `_ From f3a9596aee8799bc16cfc27f2186dd70ea1940e7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Feb 2025 18:09:13 +0000 Subject: [PATCH 198/226] Build(deps): Bump hypothesis in /dependencies/default Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.124.1 to 6.125.1. - [Release notes](https://github.com/HypothesisWorks/hypothesis/releases) - [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.124.1...hypothesis-python-6.125.1) --- updated-dependencies: - dependency-name: hypothesis dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index 67646449..a1e20930 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -1,7 +1,7 @@ attrs==24.3.0 coverage==7.6.10 exceptiongroup==1.2.2 -hypothesis==6.124.1 +hypothesis==6.125.1 iniconfig==2.0.0 packaging==24.2 pluggy==1.5.0 From e2c7bef2795c1a711331a3cc31282bc075411849 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Feb 2025 18:29:00 +0000 Subject: [PATCH 199/226] Build(deps): Bump attrs from 24.3.0 to 25.1.0 in /dependencies/default Bumps [attrs](https://github.com/sponsors/hynek) from 24.3.0 to 25.1.0. - [Commits](https://github.com/sponsors/hynek/commits) --- updated-dependencies: - dependency-name: attrs dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index a1e20930..09655362 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -1,4 +1,4 @@ -attrs==24.3.0 +attrs==25.1.0 coverage==7.6.10 exceptiongroup==1.2.2 hypothesis==6.125.1 From f77abae42945a594f4a279ddbce5137483644c28 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Feb 2025 18:42:04 +0000 Subject: [PATCH 200/226] Build(deps): Bump babel from 2.16.0 to 2.17.0 in /dependencies/docs Bumps [babel](https://github.com/python-babel/babel) from 2.16.0 to 2.17.0. - [Release notes](https://github.com/python-babel/babel/releases) - [Changelog](https://github.com/python-babel/babel/blob/master/CHANGES.rst) - [Commits](https://github.com/python-babel/babel/compare/v2.16.0...v2.17.0) --- updated-dependencies: - dependency-name: babel dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- dependencies/docs/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/docs/constraints.txt b/dependencies/docs/constraints.txt index 607c1632..af715e76 100644 --- a/dependencies/docs/constraints.txt +++ b/dependencies/docs/constraints.txt @@ -1,5 +1,5 @@ alabaster==0.7.16 -Babel==2.16.0 +Babel==2.17.0 certifi==2024.12.14 charset-normalizer==3.4.1 docutils==0.21.2 From e8a497fe39ec9f00fac4e4ac4f03ee8894a92e27 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 4 Feb 2025 00:01:53 +0000 Subject: [PATCH 201/226] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.9.3 → v0.9.4](https://github.com/astral-sh/ruff-pre-commit/compare/v0.9.3...v0.9.4) - [github.com/sirosen/check-jsonschema: 0.31.0 → 0.31.1](https://github.com/sirosen/check-jsonschema/compare/0.31.0...0.31.1) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8410474e..ba65819c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,7 +6,7 @@ repos: - id: check-merge-conflict exclude: rst$ - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.9.3 + rev: v0.9.4 hooks: - id: ruff args: [--fix] @@ -65,7 +65,7 @@ repos: - 'SC1004:' stages: [manual] - repo: https://github.com/sirosen/check-jsonschema - rev: 0.31.0 + rev: 0.31.1 hooks: - id: check-github-actions - repo: https://github.com/tox-dev/pyproject-fmt From 25891516b74090ea717c5627edc62bac866e0ba8 Mon Sep 17 00:00:00 2001 From: Will Da Silva Date: Fri, 7 Feb 2025 12:55:10 -0500 Subject: [PATCH 202/226] Fix typo in `uvloop.rst` --- docs/how-to-guides/uvloop.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/how-to-guides/uvloop.rst b/docs/how-to-guides/uvloop.rst index 889c0f9d..a796bea7 100644 --- a/docs/how-to-guides/uvloop.rst +++ b/docs/how-to-guides/uvloop.rst @@ -2,7 +2,7 @@ How to test with uvloop ======================= -Redefinig the *event_loop_policy* fixture will parametrize all async tests. The following example causes all async tests to run multiple times, once for each event loop in the fixture parameters: +Redefining the *event_loop_policy* fixture will parametrize all async tests. The following example causes all async tests to run multiple times, once for each event loop in the fixture parameters: Replace the default event loop policy in your *conftest.py:* .. code-block:: python From 7d69b5be771d768d66ffebcac5af3a0af5e739c4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Feb 2025 20:39:41 +0000 Subject: [PATCH 203/226] Build(deps): Bump certifi in /dependencies/docs Bumps [certifi](https://github.com/certifi/python-certifi) from 2024.12.14 to 2025.1.31. - [Commits](https://github.com/certifi/python-certifi/compare/2024.12.14...2025.01.31) --- updated-dependencies: - dependency-name: certifi dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- dependencies/docs/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/docs/constraints.txt b/dependencies/docs/constraints.txt index af715e76..0c1c06b4 100644 --- a/dependencies/docs/constraints.txt +++ b/dependencies/docs/constraints.txt @@ -1,6 +1,6 @@ alabaster==0.7.16 Babel==2.17.0 -certifi==2024.12.14 +certifi==2025.1.31 charset-normalizer==3.4.1 docutils==0.21.2 idna==3.10 From 68b8d726d43432aa1790900ecd91c82f9c609987 Mon Sep 17 00:00:00 2001 From: JP-Ellis Date: Tue, 14 Jan 2025 17:36:49 +1100 Subject: [PATCH 204/226] docs: how to set asyncio mode When reading the docs, it wasn't clear to me how to set asyncio's mode and I had to rely on looking at the source code (or scouring `pytest --help`). I thought it would be nice to expand the docs to be more explicit in this regard. Signed-off-by: JP-Ellis --- docs/concepts.rst | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/concepts.rst b/docs/concepts.rst index be8b775b..a25df036 100644 --- a/docs/concepts.rst +++ b/docs/concepts.rst @@ -47,8 +47,12 @@ Assigning neighboring tests to different event loop scopes is discouraged as it Test discovery modes ==================== -Pytest-asyncio provides two modes for test discovery, *strict* and *auto*. +Pytest-asyncio provides two modes for test discovery, *strict* and *auto*. This can be set through Pytest's ``--asyncio-mode`` command line flag, or through the configuration file: +.. code-block:: toml + + [tool.pytest.ini_options] + asyncio_mode = "auto" # or "strict" Strict mode ----------- From 318aed7e4d09f8c17f1499296b4fa73cf6defbc8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Feb 2025 18:38:39 +0000 Subject: [PATCH 205/226] Build(deps): Bump hypothesis in /dependencies/default Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.125.1 to 6.125.2. - [Release notes](https://github.com/HypothesisWorks/hypothesis/releases) - [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.125.1...hypothesis-python-6.125.2) --- updated-dependencies: - dependency-name: hypothesis dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index 09655362..522455ab 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -1,7 +1,7 @@ attrs==25.1.0 coverage==7.6.10 exceptiongroup==1.2.2 -hypothesis==6.125.1 +hypothesis==6.125.2 iniconfig==2.0.0 packaging==24.2 pluggy==1.5.0 From 026ec60f050f79a42050238e86326bbfb259498e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Feb 2025 19:10:19 +0000 Subject: [PATCH 206/226] Build(deps): Bump coverage in /dependencies/default Bumps [coverage](https://github.com/nedbat/coveragepy) from 7.6.10 to 7.6.11. - [Release notes](https://github.com/nedbat/coveragepy/releases) - [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst) - [Commits](https://github.com/nedbat/coveragepy/compare/7.6.10...7.6.11) --- updated-dependencies: - dependency-name: coverage dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index 522455ab..20e345b0 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -1,5 +1,5 @@ attrs==25.1.0 -coverage==7.6.10 +coverage==7.6.11 exceptiongroup==1.2.2 hypothesis==6.125.2 iniconfig==2.0.0 From def231e5f2d7340406a935f378b37a6edee757e2 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 10 Feb 2025 23:14:54 +0000 Subject: [PATCH 207/226] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.9.4 → v0.9.6](https://github.com/astral-sh/ruff-pre-commit/compare/v0.9.4...v0.9.6) - [github.com/pre-commit/mirrors-mypy: v1.14.1 → v1.15.0](https://github.com/pre-commit/mirrors-mypy/compare/v1.14.1...v1.15.0) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ba65819c..6b1c9575 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,7 +6,7 @@ repos: - id: check-merge-conflict exclude: rst$ - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.9.4 + rev: v0.9.6 hooks: - id: ruff args: [--fix] @@ -42,7 +42,7 @@ repos: - id: check-yaml - id: debug-statements - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.14.1 + rev: v1.15.0 hooks: - id: mypy exclude: ^(docs|tests)/.* From 83d53dacc60afa89b86917714a18001e0181848d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Feb 2025 19:03:18 +0000 Subject: [PATCH 208/226] Build(deps): Bump coverage in /dependencies/default Bumps [coverage](https://github.com/nedbat/coveragepy) from 7.6.11 to 7.6.12. - [Release notes](https://github.com/nedbat/coveragepy/releases) - [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst) - [Commits](https://github.com/nedbat/coveragepy/compare/7.6.11...7.6.12) --- updated-dependencies: - dependency-name: coverage dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index 20e345b0..088ca317 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -1,5 +1,5 @@ attrs==25.1.0 -coverage==7.6.11 +coverage==7.6.12 exceptiongroup==1.2.2 hypothesis==6.125.2 iniconfig==2.0.0 From 9a147888ad9198f509575a9e64fa1f93eccde248 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Feb 2025 19:39:49 +0000 Subject: [PATCH 209/226] Build(deps): Bump hypothesis in /dependencies/default Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.125.2 to 6.127.2. - [Release notes](https://github.com/HypothesisWorks/hypothesis/releases) - [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.125.2...hypothesis-python-6.127.2) --- updated-dependencies: - dependency-name: hypothesis dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index 088ca317..aa7590cb 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -1,7 +1,7 @@ attrs==25.1.0 coverage==7.6.12 exceptiongroup==1.2.2 -hypothesis==6.125.2 +hypothesis==6.127.2 iniconfig==2.0.0 packaging==24.2 pluggy==1.5.0 From 16fc93999322010ce6524d93ff28c021eb86741a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 24 Feb 2025 20:04:50 +0000 Subject: [PATCH 210/226] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.9.6 → v0.9.7](https://github.com/astral-sh/ruff-pre-commit/compare/v0.9.6...v0.9.7) - [github.com/sirosen/check-jsonschema: 0.31.1 → 0.31.2](https://github.com/sirosen/check-jsonschema/compare/0.31.1...0.31.2) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6b1c9575..f48664ca 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,7 +6,7 @@ repos: - id: check-merge-conflict exclude: rst$ - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.9.6 + rev: v0.9.7 hooks: - id: ruff args: [--fix] @@ -65,7 +65,7 @@ repos: - 'SC1004:' stages: [manual] - repo: https://github.com/sirosen/check-jsonschema - rev: 0.31.1 + rev: 0.31.2 hooks: - id: check-github-actions - repo: https://github.com/tox-dev/pyproject-fmt From 17e7078e66024283dc78b8151bb170c7c45320d8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Mar 2025 18:31:40 +0000 Subject: [PATCH 211/226] Build(deps): Bump pytest from 8.3.4 to 8.3.5 in /dependencies/default Bumps [pytest](https://github.com/pytest-dev/pytest) from 8.3.4 to 8.3.5. - [Release notes](https://github.com/pytest-dev/pytest/releases) - [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest/compare/8.3.4...8.3.5) --- updated-dependencies: - dependency-name: pytest dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index aa7590cb..54b15fa6 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -5,7 +5,7 @@ hypothesis==6.127.2 iniconfig==2.0.0 packaging==24.2 pluggy==1.5.0 -pytest==8.3.4 +pytest==8.3.5 sortedcontainers==2.4.0 tomli==2.2.1 typing_extensions==4.12.2 From 5c6b4dc294d494e99c3bfec250d2c7c442092ee8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Mar 2025 18:31:36 +0000 Subject: [PATCH 212/226] Build(deps): Bump hypothesis in /dependencies/default Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.127.2 to 6.127.5. - [Release notes](https://github.com/HypothesisWorks/hypothesis/releases) - [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.127.2...hypothesis-python-6.127.5) --- updated-dependencies: - dependency-name: hypothesis dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index 54b15fa6..10fdef75 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -1,7 +1,7 @@ attrs==25.1.0 coverage==7.6.12 exceptiongroup==1.2.2 -hypothesis==6.127.2 +hypothesis==6.127.5 iniconfig==2.0.0 packaging==24.2 pluggy==1.5.0 From cab894a1f6bb7aaf18a1413ba26daff1224298a0 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 3 Mar 2025 20:44:34 +0000 Subject: [PATCH 213/226] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.9.7 → v0.9.9](https://github.com/astral-sh/ruff-pre-commit/compare/v0.9.7...v0.9.9) - [github.com/tox-dev/pyproject-fmt: v2.5.0 → v2.5.1](https://github.com/tox-dev/pyproject-fmt/compare/v2.5.0...v2.5.1) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f48664ca..fc0c06a5 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,7 +6,7 @@ repos: - id: check-merge-conflict exclude: rst$ - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.9.7 + rev: v0.9.9 hooks: - id: ruff args: [--fix] @@ -69,7 +69,7 @@ repos: hooks: - id: check-github-actions - repo: https://github.com/tox-dev/pyproject-fmt - rev: v2.5.0 + rev: v2.5.1 hooks: - id: pyproject-fmt # https://pyproject-fmt.readthedocs.io/en/latest/#calculating-max-supported-python-version From 50da623a9a42180adecc9098315f3d95572c7299 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Mar 2025 18:30:06 +0000 Subject: [PATCH 214/226] Build(deps): Bump jinja2 from 3.1.5 to 3.1.6 in /dependencies/docs Bumps [jinja2](https://github.com/pallets/jinja) from 3.1.5 to 3.1.6. - [Release notes](https://github.com/pallets/jinja/releases) - [Changelog](https://github.com/pallets/jinja/blob/main/CHANGES.rst) - [Commits](https://github.com/pallets/jinja/compare/3.1.5...3.1.6) --- updated-dependencies: - dependency-name: jinja2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dependencies/docs/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/docs/constraints.txt b/dependencies/docs/constraints.txt index 0c1c06b4..85afd831 100644 --- a/dependencies/docs/constraints.txt +++ b/dependencies/docs/constraints.txt @@ -5,7 +5,7 @@ charset-normalizer==3.4.1 docutils==0.21.2 idna==3.10 imagesize==1.4.1 -Jinja2==3.1.5 +Jinja2==3.1.6 MarkupSafe==3.0.2 packaging==24.2 Pygments==2.19.1 From d5eced484f4b55d2832f4feb2289577c5e49f02b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Mar 2025 18:25:12 +0000 Subject: [PATCH 215/226] Build(deps): Bump hypothesis in /dependencies/default Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.127.5 to 6.128.2. - [Release notes](https://github.com/HypothesisWorks/hypothesis/releases) - [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.127.5...hypothesis-python-6.128.2) --- updated-dependencies: - dependency-name: hypothesis dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index 10fdef75..94a39ae5 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -1,7 +1,7 @@ attrs==25.1.0 coverage==7.6.12 exceptiongroup==1.2.2 -hypothesis==6.127.5 +hypothesis==6.128.2 iniconfig==2.0.0 packaging==24.2 pluggy==1.5.0 From ef35ba137f51eb391d42d663a7ee2fd02c7f62c5 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 10 Mar 2025 20:13:52 +0000 Subject: [PATCH 216/226] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.9.9 → v0.9.10](https://github.com/astral-sh/ruff-pre-commit/compare/v0.9.9...v0.9.10) - [github.com/sirosen/check-jsonschema: 0.31.2 → 0.31.3](https://github.com/sirosen/check-jsonschema/compare/0.31.2...0.31.3) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index fc0c06a5..bc3d8be1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,7 +6,7 @@ repos: - id: check-merge-conflict exclude: rst$ - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.9.9 + rev: v0.9.10 hooks: - id: ruff args: [--fix] @@ -65,7 +65,7 @@ repos: - 'SC1004:' stages: [manual] - repo: https://github.com/sirosen/check-jsonschema - rev: 0.31.2 + rev: 0.31.3 hooks: - id: check-github-actions - repo: https://github.com/tox-dev/pyproject-fmt From c2622628b6ca1f2d583df375cc370070c2c0c54e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Mar 2025 18:27:46 +0000 Subject: [PATCH 217/226] Build(deps): Bump coverage from 7.6.12 to 7.7.0 in /dependencies/default Bumps [coverage](https://github.com/nedbat/coveragepy) from 7.6.12 to 7.7.0. - [Release notes](https://github.com/nedbat/coveragepy/releases) - [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst) - [Commits](https://github.com/nedbat/coveragepy/compare/7.6.12...7.7.0) --- updated-dependencies: - dependency-name: coverage dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index 94a39ae5..338cf7e3 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -1,5 +1,5 @@ attrs==25.1.0 -coverage==7.6.12 +coverage==7.7.0 exceptiongroup==1.2.2 hypothesis==6.128.2 iniconfig==2.0.0 From 5d90b296218ef8c3d2bbafd70736bece18eeb984 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Mar 2025 18:30:12 +0000 Subject: [PATCH 218/226] Build(deps): Bump hypothesis in /dependencies/default Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.128.2 to 6.129.3. - [Release notes](https://github.com/HypothesisWorks/hypothesis/releases) - [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.128.2...hypothesis-python-6.129.3) --- updated-dependencies: - dependency-name: hypothesis dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index 338cf7e3..68d4b4dc 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -1,7 +1,7 @@ attrs==25.1.0 coverage==7.7.0 exceptiongroup==1.2.2 -hypothesis==6.128.2 +hypothesis==6.129.3 iniconfig==2.0.0 packaging==24.2 pluggy==1.5.0 From cca587ea4f2c09b1b25b56cb4a22c44677cf27fc Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 17 Mar 2025 20:20:39 +0000 Subject: [PATCH 219/226] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.9.10 → v0.11.0](https://github.com/astral-sh/ruff-pre-commit/compare/v0.9.10...v0.11.0) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index bc3d8be1..b3fe55da 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,7 +6,7 @@ repos: - id: check-merge-conflict exclude: rst$ - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.9.10 + rev: v0.11.0 hooks: - id: ruff args: [--fix] From aa82c574feae8611170150222b41bd4c1e72855d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Mar 2025 20:05:14 +0000 Subject: [PATCH 220/226] Build(deps): Bump iniconfig from 2.0.0 to 2.1.0 in /dependencies/default Bumps [iniconfig](https://github.com/pytest-dev/iniconfig) from 2.0.0 to 2.1.0. - [Release notes](https://github.com/pytest-dev/iniconfig/releases) - [Changelog](https://github.com/pytest-dev/iniconfig/blob/main/CHANGELOG) - [Commits](https://github.com/pytest-dev/iniconfig/compare/v2.0.0...v2.1.0) --- updated-dependencies: - dependency-name: iniconfig dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index 68d4b4dc..c11fc0d6 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -2,7 +2,7 @@ attrs==25.1.0 coverage==7.7.0 exceptiongroup==1.2.2 hypothesis==6.129.3 -iniconfig==2.0.0 +iniconfig==2.1.0 packaging==24.2 pluggy==1.5.0 pytest==8.3.5 From 66804094397afc7b4c905c113209a89e4df7a3d5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Mar 2025 20:55:51 +0000 Subject: [PATCH 221/226] Build(deps): Bump coverage from 7.7.0 to 7.7.1 in /dependencies/default Bumps [coverage](https://github.com/nedbat/coveragepy) from 7.7.0 to 7.7.1. - [Release notes](https://github.com/nedbat/coveragepy/releases) - [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst) - [Commits](https://github.com/nedbat/coveragepy/compare/7.7.0...7.7.1) --- updated-dependencies: - dependency-name: coverage dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index c11fc0d6..439ddd4c 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -1,5 +1,5 @@ attrs==25.1.0 -coverage==7.7.0 +coverage==7.7.1 exceptiongroup==1.2.2 hypothesis==6.129.3 iniconfig==2.1.0 From 9a455516ea423fd29c3f45878713ca1715b899e6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Mar 2025 20:55:16 +0000 Subject: [PATCH 222/226] Build(deps): Bump hypothesis in /dependencies/default Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.129.3 to 6.130.3. - [Release notes](https://github.com/HypothesisWorks/hypothesis/releases) - [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.129.3...hypothesis-python-6.130.3) --- updated-dependencies: - dependency-name: hypothesis dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index 439ddd4c..98b6e063 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -1,7 +1,7 @@ attrs==25.1.0 coverage==7.7.1 exceptiongroup==1.2.2 -hypothesis==6.129.3 +hypothesis==6.130.3 iniconfig==2.1.0 packaging==24.2 pluggy==1.5.0 From 78191c98ed4792cd9352bfff0885cc041ee2b1ed Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 24 Mar 2025 20:11:51 +0000 Subject: [PATCH 223/226] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.11.0 → v0.11.2](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.0...v0.11.2) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b3fe55da..973ac3f5 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,7 +6,7 @@ repos: - id: check-merge-conflict exclude: rst$ - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.11.0 + rev: v0.11.2 hooks: - id: ruff args: [--fix] From 01c22ffb63f3bdd158b7d35bd14f8a45ba35338e Mon Sep 17 00:00:00 2001 From: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Date: Tue, 25 Mar 2025 07:07:01 +0100 Subject: [PATCH 224/226] build: Update project metadata to use SPDX license identifier --- pyproject.toml | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index c503970e..b368b481 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,10 +1,8 @@ [build-system] build-backend = "setuptools.build_meta" - requires = [ - "setuptools>=51", + "setuptools>=77", "setuptools-scm[toml]>=6.2", - "wheel>=0.36", ] [project] @@ -12,7 +10,10 @@ name = "pytest-asyncio" description = "Pytest support for asyncio" readme.content-type = "text/x-rst" readme.file = "README.rst" -license.text = "Apache 2.0" +license = "Apache-2.0" +license-files = [ + "LICENSE", +] authors = [ { name = "Tin Tvrtković ", email = "tinchester@gmail.com" }, ] @@ -22,7 +23,6 @@ classifiers = [ "Framework :: AsyncIO", "Framework :: Pytest", "Intended Audience :: Developers", - "License :: OSI Approved :: Apache Software License", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", @@ -60,9 +60,6 @@ packages = [ "pytest_asyncio", ] include-package-data = true -license-files = [ - "LICENSE", -] [tool.setuptools_scm] write_to = "pytest_asyncio/_version.py" From 498e8a7786b85027bd8e9992f8af6a05a90e3786 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 25 Mar 2025 06:08:21 +0000 Subject: [PATCH 225/226] Build(deps): Bump attrs from 25.1.0 to 25.3.0 in /dependencies/default Bumps [attrs](https://github.com/sponsors/hynek) from 25.1.0 to 25.3.0. - [Commits](https://github.com/sponsors/hynek/commits) --- updated-dependencies: - dependency-name: attrs dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- dependencies/default/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/default/constraints.txt b/dependencies/default/constraints.txt index 98b6e063..db8d6faf 100644 --- a/dependencies/default/constraints.txt +++ b/dependencies/default/constraints.txt @@ -1,4 +1,4 @@ -attrs==25.1.0 +attrs==25.3.0 coverage==7.7.1 exceptiongroup==1.2.2 hypothesis==6.130.3 From 4f8ce457b0a52eba1233349e740ca9e7fb400804 Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Tue, 25 Mar 2025 07:15:44 +0100 Subject: [PATCH 226/226] docs: Prepare release of v0.26.0. --- docs/reference/changelog.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference/changelog.rst b/docs/reference/changelog.rst index dd703fa1..11c35a1b 100644 --- a/docs/reference/changelog.rst +++ b/docs/reference/changelog.rst @@ -2,7 +2,7 @@ Changelog ========= -0.26.0 (UNRELEASED) +0.26.0 (2025-03-25) =================== - Adds configuration option that sets default event loop scope for all tests `#793 `_ - Improved type annotations for ``pytest_asyncio.fixture`` `#1045 `_