From 8360902e8e979887f49817ce260da960e8c8391d Mon Sep 17 00:00:00 2001 From: Piper Merriam Date: Fri, 10 May 2019 13:51:59 -0600 Subject: [PATCH 01/10] Add mechanism for explicit marking of fixtures which should be run under asyncio --- pytest_asyncio/__init__.py | 2 + pytest_asyncio/plugin.py | 143 ++++++++++++++++++++++++------------- 2 files changed, 97 insertions(+), 48 deletions(-) diff --git a/pytest_asyncio/__init__.py b/pytest_asyncio/__init__.py index 88aaa15d..564d0e2f 100644 --- a/pytest_asyncio/__init__.py +++ b/pytest_asyncio/__init__.py @@ -1,2 +1,4 @@ """The main point for importing pytest-asyncio items.""" __version__ = "0.11.0dev0" + +from .plugin import asyncio_fixture diff --git a/pytest_asyncio/plugin.py b/pytest_asyncio/plugin.py index 24450bf7..297ba799 100644 --- a/pytest_asyncio/plugin.py +++ b/pytest_asyncio/plugin.py @@ -19,6 +19,40 @@ def transfer_markers(*args, **kwargs): # noqa from inspect import isasyncgenfunction +def pytest_addoption(parser): + parser.addini( + "asyncio_mode", + "should pytest-asyncio handle all async functions?", + type="bool", + # This is defaulted to true to retain previous behavior but should be + # updated to `False` after a deprecation cycle so that the library + # plays nice with others by default. + default=True, + ) + + +# Intentional that this only allows function scoped fixture without any way to +# pass through `scope` to the underlying `pytest.fixture` wrapper. +def asyncio_fixture(func): + func._force_asyncio_fixture = True + return pytest.fixture(func) + + +def _has_explicit_asyncio_mark(value): + return getattr(value, "_force_asyncio_fixture", False) + +def _is_asyncio_fixture(func, coerce_asyncio, kwargs): + if _has_explicit_asyncio_mark(func): + return True + elif (coerce_asyncio and + (asyncio.iscoroutinefunction(func) or inspect.isasyncgenfunction(func))): + return True + elif any(_has_explicit_asyncio_mark(value) for value in kwargs.values()): + return True + else: + return False + + def _is_coroutine(obj): """Check to see if an object is really an asyncio coroutine.""" return asyncio.iscoroutinefunction(obj) or inspect.isgeneratorfunction(obj) @@ -65,54 +99,67 @@ def pytest_fixture_setup(fixturedef, request): fixturedef.addfinalizer(lambda: policy.set_event_loop(old_loop)) return - if isasyncgenfunction(fixturedef.func): - # This is an async generator function. Wrap it accordingly. - generator = fixturedef.func - - strip_request = False - if 'request' not in fixturedef.argnames: - fixturedef.argnames += ('request', ) - strip_request = True - - def wrapper(*args, **kwargs): - request = kwargs['request'] - if strip_request: - del kwargs['request'] - - gen_obj = generator(*args, **kwargs) - - async def setup(): - res = await gen_obj.__anext__() - return res - - def finalizer(): - """Yield again, to finalize.""" - async def async_finalizer(): - try: - await gen_obj.__anext__() - except StopAsyncIteration: - pass - else: - msg = "Async generator fixture didn't stop." - msg += "Yield only once." - raise ValueError(msg) - asyncio.get_event_loop().run_until_complete(async_finalizer()) - - request.addfinalizer(finalizer) - return asyncio.get_event_loop().run_until_complete(setup()) - - fixturedef.func = wrapper - elif inspect.iscoroutinefunction(fixturedef.func): - coro = fixturedef.func - - def wrapper(*args, **kwargs): - async def setup(): - res = await coro(*args, **kwargs) - return res - - return asyncio.get_event_loop().run_until_complete(setup()) - - fixturedef.func = wrapper + is_asyncio_test = request.node.get_closest_marker("asyncio") is not None + is_asyncio_mode = request.node.config.getini("asyncio_mode") + + coerce_asyncio = is_asyncio_test or is_asyncio_mode + + kwargs = { + name: request.getfixturevalue(name) + for name in fixturedef.argnames + } + + if _is_asyncio_fixture(fixturedef.func, coerce_asyncio, kwargs): + if isasyncgenfunction(fixturedef.func): + # This is an async generator function. Wrap it accordingly. + generator = fixturedef.func + + strip_request = False + if 'request' not in fixturedef.argnames: + fixturedef.argnames += ('request', ) + strip_request = True + + def wrapper(*args, **kwargs): + request = kwargs['request'] + if strip_request: + del kwargs['request'] + + gen_obj = generator(*args, **kwargs) + + async def setup(): + res = await gen_obj.__anext__() + return res + + def finalizer(): + """Yield again, to finalize.""" + async def async_finalizer(): + try: + await gen_obj.__anext__() + except StopAsyncIteration: + pass + else: + msg = "Async generator fixture didn't stop." + msg += "Yield only once." + raise ValueError(msg) + asyncio.get_event_loop().run_until_complete(async_finalizer()) + + request.addfinalizer(finalizer) + return asyncio.get_event_loop().run_until_complete(setup()) + wrapper._is_asyncio_fixture = True + + fixturedef.func = wrapper + elif inspect.iscoroutinefunction(fixturedef.func): + coro = fixturedef.func + + def wrapper(*args, **kwargs): + async def setup(): + res = await coro(*args, **kwargs) + return res + + return asyncio.get_event_loop().run_until_complete(setup()) + wrapper._is_asyncio_fixture = True + + fixturedef.func = wrapper yield From 6fc12d8e9f858537692d12db363a23534f2738eb Mon Sep 17 00:00:00 2001 From: Andrew Svetlov Date: Fri, 7 Jan 2022 14:31:33 +0200 Subject: [PATCH 02/10] Add __all__ --- pytest_asyncio/__init__.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pytest_asyncio/__init__.py b/pytest_asyncio/__init__.py index 564d0e2f..8c3a39c6 100644 --- a/pytest_asyncio/__init__.py +++ b/pytest_asyncio/__init__.py @@ -2,3 +2,6 @@ __version__ = "0.11.0dev0" from .plugin import asyncio_fixture + + +__all__ = ('asyncio_fixture',) From ce6bbf53f885a34fd85b60974cbbfec748e46d48 Mon Sep 17 00:00:00 2001 From: Andrew Svetlov Date: Fri, 7 Jan 2022 20:44:47 +0200 Subject: [PATCH 03/10] Reformat --- pytest_asyncio/plugin.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pytest_asyncio/plugin.py b/pytest_asyncio/plugin.py index 6484a325..f00a6249 100644 --- a/pytest_asyncio/plugin.py +++ b/pytest_asyncio/plugin.py @@ -209,8 +209,10 @@ def pytest_fixture_setup(fixturedef, request): code = func.__code__ except AttributeError: code = func.__func__.__code__ - name = (f"") + name = ( + f"" + ) warnings.warn( LEGACY_ASYNCIO_FIXTURE.format(name=name), pytest.PytestDeprecationWarning, From b6f3ca0de2f7d7b3cc26de6ca471b466fd286f9e Mon Sep 17 00:00:00 2001 From: Andrew Svetlov Date: Fri, 7 Jan 2022 22:11:23 +0200 Subject: [PATCH 04/10] Work on --- pytest_asyncio/plugin.py | 11 +-- tests/modes/test_auto_mode.py | 92 +++++++++++++++++++++++++ tests/modes/test_legacy_mode.py | 116 ++++++++++++++++++++++++++++++++ 3 files changed, 215 insertions(+), 4 deletions(-) create mode 100644 tests/modes/test_auto_mode.py create mode 100644 tests/modes/test_legacy_mode.py diff --git a/pytest_asyncio/plugin.py b/pytest_asyncio/plugin.py index f00a6249..b24b9223 100644 --- a/pytest_asyncio/plugin.py +++ b/pytest_asyncio/plugin.py @@ -128,12 +128,15 @@ def pytest_pycollect_makeitem(collector, name, obj): """A pytest hook to collect asyncio coroutines.""" if collector.funcnamefilter(name) and _is_coroutine(obj): item = pytest.Function.from_parent(collector, name=name) - if "asyncio" not in item.keywords: - if _get_asyncio_mode(item.config) == Mode.AUTO: - # implicitly add asyncio marker if asyncio mode is on - item.add_marker("asyncio") if "asyncio" in item.keywords: return list(collector._genfunctions(name, obj)) + else: + if _get_asyncio_mode(item.config) == Mode.AUTO: + # implicitly add asyncio marker if asyncio mode is on + ret = list(collector._genfunctions(name, obj)) + for elem in ret: + elem.add_marker("asyncio") + return ret class FixtureStripper: diff --git a/tests/modes/test_auto_mode.py b/tests/modes/test_auto_mode.py new file mode 100644 index 00000000..2011161b --- /dev/null +++ b/tests/modes/test_auto_mode.py @@ -0,0 +1,92 @@ +from textwrap import dedent +import re + +pytest_plugins = "pytester" + + +def test_auto_mode_cmdline(pytester): + pytester.makepyfile( + dedent( + """\ + import asyncio + import pytest + + pytest_plugins = 'pytest_asyncio' + + async def test_a(): + await asyncio.sleep(0) + """ + ) + ) + result = pytester.runpytest("--asyncio-mode=auto") + result.assert_outcomes(passed=1) + + +def test_auto_mode_cfg(pytester): + pytester.makepyfile( + dedent( + """\ + import asyncio + import pytest + + pytest_plugins = 'pytest_asyncio' + + async def test_a(): + await asyncio.sleep(0) + """ + ) + ) + pytester.makefile(".ini", pytest="[pytest]\nasyncio_mode = auto\n") + result = pytester.runpytest() + result.assert_outcomes(passed=1) + + +def test_auto_mode_async_fixture(pytester): + pytester.makepyfile( + dedent( + """\ + import asyncio + import pytest + + pytest_plugins = 'pytest_asyncio' + + @pytest.fixture + async def fixture_a(): + await asyncio.sleep(0) + return 1 + + async def test_a(fixture_a): + await asyncio.sleep(0) + assert fixture_a == 1 + """ + ) + ) + result = pytester.runpytest("--asyncio-mode=auto") + result.assert_outcomes(passed=1) + + +def test_auto_mode_method_fixture(pytester): + pytester.makepyfile( + dedent( + """\ + import asyncio + import pytest + + pytest_plugins = 'pytest_asyncio' + + + class TestA: + + @pytest.fixture + async def fixture_a(self): + await asyncio.sleep(0) + return 1 + + async def test_a(self, fixture_a): + await asyncio.sleep(0) + assert fixture_a == 1 + """ + ) + ) + result = pytester.runpytest("--asyncio-mode=auto") + result.assert_outcomes(passed=1) diff --git a/tests/modes/test_legacy_mode.py b/tests/modes/test_legacy_mode.py new file mode 100644 index 00000000..6ed4d59a --- /dev/null +++ b/tests/modes/test_legacy_mode.py @@ -0,0 +1,116 @@ +from textwrap import dedent +import re + +pytest_plugins = "pytester" + + +LEGACY_MODE = ( + "The 'asyncio_mode' default value will change to 'strict' in future, " + "please explicitly use 'asyncio_mode=strict' or 'asyncio_mode=auto' " + "in pytest configuration file." +) + +LEGACY_ASYNCIO_FIXTURE = ( + "'@pytest.fixture' is applied to {name} " + "in 'legacy' mode, " + "please replace it with '@pytest_asyncio.pytest_asyncio' as a preparation " + "for switching to 'strict' mode (or use 'auto' mode to seamlessly handle " + "all these fixtures as asyncio-driven)." +).format(name="*") + + +def test_warning_for_legacy_mode_cmdline(pytester): + pytester.makepyfile( + dedent( + """\ + import asyncio + import pytest + + pytest_plugins = 'pytest_asyncio' + + @pytest.mark.asyncio + async def test_a(): + await asyncio.sleep(0) + """ + ) + ) + result = pytester.runpytest("--asyncio-mode=legacy") + assert result.parseoutcomes()["warnings"] == 1 + result.stdout.fnmatch_lines(["*" + LEGACY_MODE + "*"]) + + +def test_warning_for_legacy_mode_cfg(pytester): + pytester.makepyfile( + dedent( + """\ + import asyncio + import pytest + + pytest_plugins = 'pytest_asyncio' + + @pytest.mark.asyncio + async def test_a(): + await asyncio.sleep(0) + """ + ) + ) + pytester.makefile(".ini", pytest="[pytest]\nasyncio_mode = legacy\n") + result = pytester.runpytest() + assert result.parseoutcomes()["warnings"] == 1 + result.stdout.fnmatch_lines(["*" + LEGACY_MODE + "*"]) + result.stdout.no_fnmatch_line("*" + LEGACY_ASYNCIO_FIXTURE + "*") + + +def test_warning_for_legacy_fixture(pytester): + pytester.makepyfile( + dedent( + """\ + import asyncio + import pytest + + pytest_plugins = 'pytest_asyncio' + + @pytest.fixture + async def fixture_a(): + await asyncio.sleep(0) + return 1 + + @pytest.mark.asyncio + async def test_a(fixture_a): + await asyncio.sleep(0) + assert fixture_a == 1 + """ + ) + ) + result = pytester.runpytest("--asyncio-mode=legacy") + assert result.parseoutcomes()["warnings"] == 2 + result.stdout.fnmatch_lines(["*" + LEGACY_ASYNCIO_FIXTURE + "*"]) + + +def test_warning_for_legacy_method_fixture(pytester): + pytester.makepyfile( + dedent( + """\ + import asyncio + import pytest + + pytest_plugins = 'pytest_asyncio' + + + class TestA: + + @pytest.fixture + async def fixture_a(self): + await asyncio.sleep(0) + return 1 + + @pytest.mark.asyncio + async def test_a(self, fixture_a): + await asyncio.sleep(0) + assert fixture_a == 1 + """ + ) + ) + result = pytester.runpytest("--asyncio-mode=legacy") + assert result.parseoutcomes()["warnings"] == 2 + result.stdout.fnmatch_lines(["*" + LEGACY_ASYNCIO_FIXTURE + "*"]) From da87ba6bb97e0c28aa5cbd8da82335266aad8ef0 Mon Sep 17 00:00:00 2001 From: Andrew Svetlov Date: Fri, 7 Jan 2022 22:44:06 +0200 Subject: [PATCH 05/10] Add tests --- pytest_asyncio/__init__.py | 4 +- pytest_asyncio/plugin.py | 16 +++++--- tests/modes/test_auto_mode.py | 1 - tests/modes/test_legacy_mode.py | 1 - tests/modes/test_strict_mode.py | 70 +++++++++++++++++++++++++++++++++ tests/test_asyncio_fixture.py | 39 ++++++++++++++++++ 6 files changed, 121 insertions(+), 10 deletions(-) create mode 100644 tests/modes/test_strict_mode.py create mode 100644 tests/test_asyncio_fixture.py diff --git a/pytest_asyncio/__init__.py b/pytest_asyncio/__init__.py index e39b581e..0da62156 100644 --- a/pytest_asyncio/__init__.py +++ b/pytest_asyncio/__init__.py @@ -1,7 +1,7 @@ """The main point for importing pytest-asyncio items.""" __version__ = "0.16.0" -from .plugin import asyncio_fixture +from .plugin import fixture -__all__ = ("asyncio_fixture",) +__all__ = ("fixture",) diff --git a/pytest_asyncio/plugin.py b/pytest_asyncio/plugin.py index b24b9223..49a15999 100644 --- a/pytest_asyncio/plugin.py +++ b/pytest_asyncio/plugin.py @@ -59,15 +59,18 @@ def pytest_addoption(parser, pluginmanager): ) -def asyncio_fixture(fixture_function=None, **kwargs): +def fixture(fixture_function=None, **kwargs): if fixture_function is not None: + _set_explicit_asyncio_mark(fixture_function) + return pytest.fixture(fixture_function, **kwargs) - @functools.wraps(asyncio_fixture) - def inner(fixture_function, **kwargs): - return asyncio_fixture(fixture_function, **kwargs) + else: - _set_explicit_asyncio_mark(fixture_function) - return pytest.fixture(fixture_function, **kwargs) + @functools.wraps(fixture) + def inner(fixture_function): + return fixture(fixture_function, **kwargs) + + return inner def _has_explicit_asyncio_mark(obj): @@ -77,6 +80,7 @@ def _has_explicit_asyncio_mark(obj): def _set_explicit_asyncio_mark(obj): if hasattr(obj, "__func__"): + # instance method, check the function object obj = obj.__func__ obj._force_asyncio_fixture = True diff --git a/tests/modes/test_auto_mode.py b/tests/modes/test_auto_mode.py index 2011161b..980b0b04 100644 --- a/tests/modes/test_auto_mode.py +++ b/tests/modes/test_auto_mode.py @@ -1,5 +1,4 @@ from textwrap import dedent -import re pytest_plugins = "pytester" diff --git a/tests/modes/test_legacy_mode.py b/tests/modes/test_legacy_mode.py index 6ed4d59a..42c31eeb 100644 --- a/tests/modes/test_legacy_mode.py +++ b/tests/modes/test_legacy_mode.py @@ -1,5 +1,4 @@ from textwrap import dedent -import re pytest_plugins = "pytester" diff --git a/tests/modes/test_strict_mode.py b/tests/modes/test_strict_mode.py new file mode 100644 index 00000000..7b574012 --- /dev/null +++ b/tests/modes/test_strict_mode.py @@ -0,0 +1,70 @@ +from textwrap import dedent + +pytest_plugins = "pytester" + + +def test_strict_mode_cmdline(pytester): + pytester.makepyfile( + dedent( + """\ + import asyncio + import pytest + + pytest_plugins = 'pytest_asyncio' + + @pytest.mark.asyncio + async def test_a(): + await asyncio.sleep(0) + """ + ) + ) + result = pytester.runpytest("--asyncio-mode=strict") + result.assert_outcomes(passed=1) + + +def test_strict_mode_cfg(pytester): + pytester.makepyfile( + dedent( + """\ + import asyncio + import pytest + + pytest_plugins = 'pytest_asyncio' + + @pytest.mark.asyncio + async def test_a(): + await asyncio.sleep(0) + """ + ) + ) + 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.makepyfile( + dedent( + """\ + import asyncio + import pytest + import pytest_asyncio + + pytest_plugins = 'pytest_asyncio' + + class TestA: + + @pytest_asyncio.fixture + async def fixture_a(self): + await asyncio.sleep(0) + return 1 + + @pytest.mark.asyncio + async def test_a(self, fixture_a): + await asyncio.sleep(0) + assert fixture_a == 1 + """ + ) + ) + result = pytester.runpytest("--asyncio-mode=auto") + result.assert_outcomes(passed=1) diff --git a/tests/test_asyncio_fixture.py b/tests/test_asyncio_fixture.py new file mode 100644 index 00000000..824956d8 --- /dev/null +++ b/tests/test_asyncio_fixture.py @@ -0,0 +1,39 @@ +import asyncio +import pytest_asyncio +import pytest + + +@pytest_asyncio.fixture +async def fixture_bare(): + await asyncio.sleep(0) + return 1 + + +@pytest.mark.asyncio +async def test_bare_fixture(fixture_bare): + await asyncio.sleep(0) + assert fixture_bare == 1 + + +@pytest_asyncio.fixture(name="new_fixture_name") +async def fixture_with_name(request): + await asyncio.sleep(0) + return request.fixturename + + +@pytest.mark.asyncio +async def test_fixture_with_name(new_fixture_name): + await asyncio.sleep(0) + assert new_fixture_name == "new_fixture_name" + + +@pytest_asyncio.fixture(params=[2, 4]) +async def fixture_with_params(request): + await asyncio.sleep(0) + return request.param + + +@pytest.mark.asyncio +async def test_fixture_with_params(fixture_with_params): + await asyncio.sleep(0) + assert fixture_with_params % 2 == 0 From 2523772d65c30ff18c2a2ac82b228e7b213f1204 Mon Sep 17 00:00:00 2001 From: Andrew Svetlov Date: Fri, 7 Jan 2022 23:29:18 +0200 Subject: [PATCH 06/10] Update README --- README.rst | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 79 insertions(+), 3 deletions(-) diff --git a/README.rst b/README.rst index 7330e1a9..3698e78a 100644 --- a/README.rst +++ b/README.rst @@ -39,6 +39,9 @@ Features - pytest markers for treating tests as asyncio coroutines - easy testing with non-default event loops - support for `async def` fixtures and async generator fixtures +- support *auto* mode to handle all async fixtures and tests automatically by asyncio; + provide *strict* mode if a test suite should work with different async frameworks + simultaneously, e.g. ``asyncio`` and ``trio``. Installation ------------ @@ -51,6 +54,70 @@ To install pytest-asyncio, simply: This is enough for pytest to pick up pytest-asyncio. +Modes +----- + +Strting from ``pytest-asyncio>=0.17``, three modes are provided: *auto*, *strict* and +*legacy* (deault). + +The mode can be set by ``asyncio_mode`` configuration option in `configuration file +`_: + +.. code-block:: ini + + # pytest.ini + [pytest] + asyncio_mode = auto + +The value can be overriden by command-line option for ``pytest`` invocation: + +.. code-block:: bash + + $ pytest tests --asyncio-mode=strict + +Auto mode +~~~~~~~~~ + +When the mode is auto, all discovered *async* tests are considered *asyncio-driven* even +if they have no ``@pytest.mark.asyncio`` marker. + +All async fixtures are considered *asyncio-driven* as well, even if they are decorated +with a regular ``@pytest.fixture`` decorator instead of dedicated +``@pytest_asyncio.fixture`` counterpart. + +*asyncio-driven* means that tests and fixtures are executed by ``pytest-asyncio`` +plugin. + +This mode requires the simpliest tests and fixtures configuration and is +recommended for default usage *unless* the same project and its test suite should +execute tests from different async frameworks, e.g. ``asyncio`` and ``trio``. In this +case, auto-handling can break tests designed for other framework; plase use *strict* +mode instead. + +Strict mode +~~~~~~~~~~~ + +Strict mode enforces ``@pytest.mark.asyncio`` and ``@pytest_asyncio.fixture`` usage. +Without these markers, tests and fixtures are not considered as *asyncio-driven*, other +pytest plugin can handle them. + +Please use this mode if multiple async frameworks should be combined in the same test +suite. + + +Legacy mode +~~~~~~~~~~~ + +This mode follows rules used by ``pytest-asyncio<0.17``: tests are not auto-marked but +fixtures are. + +This mode is used by default for the sake of backward compatibility, deprecation +warnings are emitted with suggestion to either switching to ``auto`` mode or using +``strict`` mode with ``@pytest_asyncio.fixture`` decorators. + +In future, the default will be changed. + + Fixtures -------- @@ -116,16 +183,18 @@ Work just like their TCP counterparts but return unused UDP ports. Async fixtures ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Asynchronous fixtures are defined just like ordinary pytest fixtures, except they should be coroutines or asynchronous generators. +Asynchronous fixtures are defined just like ordinary pytest fixtures, except they should be decorated with ``@pytest_asyncio.fixture``. .. code-block:: python3 - @pytest.fixture + import pytest_asyncio + + @pytest_asyncio.fixture async def async_gen_fixture(): await asyncio.sleep(0.1) yield 'a value' - @pytest.fixture(scope='module') + @pytest_asyncio.fixture(scope='module') async def async_fixture(): return await asyncio.sleep(0.1) @@ -134,6 +203,9 @@ 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. +*auto* and *legacy* mode automatically converts async fixtures declared with the +standard ``@pytest.fixture`` decorator to *asyncio-driven* versions. + Markers ------- @@ -164,6 +236,10 @@ Only test coroutines will be affected (by default, coroutines prefixed by """No marker!""" await asyncio.sleep(0, loop=event_loop) +In *auto* mode, the ``pytest.mark.asyncio`` marker can be omited, the merker is added +automatically to *async* test functions. + + .. |pytestmark| replace:: ``pytestmark`` .. _pytestmark: http://doc.pytest.org/en/latest/example/markers.html#marking-whole-classes-or-modules From 41892a167df355d35fd95cef405b62ae399f618b Mon Sep 17 00:00:00 2001 From: Andrew Svetlov Date: Fri, 7 Jan 2022 23:33:52 +0200 Subject: [PATCH 07/10] Update README.rst Co-authored-by: Thomas Grainger --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 3698e78a..c19deec7 100644 --- a/README.rst +++ b/README.rst @@ -57,7 +57,7 @@ This is enough for pytest to pick up pytest-asyncio. Modes ----- -Strting from ``pytest-asyncio>=0.17``, three modes are provided: *auto*, *strict* and +Starting from ``pytest-asyncio>=0.17``, three modes are provided: *auto*, *strict* and *legacy* (deault). The mode can be set by ``asyncio_mode`` configuration option in `configuration file From eeaec64c1a9dbd7bd42b55219860c6d198014ffc Mon Sep 17 00:00:00 2001 From: Andrew Svetlov Date: Sat, 8 Jan 2022 18:23:51 +0200 Subject: [PATCH 08/10] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Tin Tvrtković --- README.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index c19deec7..4a6a350b 100644 --- a/README.rst +++ b/README.rst @@ -58,7 +58,7 @@ Modes ----- Starting from ``pytest-asyncio>=0.17``, three modes are provided: *auto*, *strict* and -*legacy* (deault). +*legacy* (default). The mode can be set by ``asyncio_mode`` configuration option in `configuration file `_: @@ -88,7 +88,7 @@ with a regular ``@pytest.fixture`` decorator instead of dedicated *asyncio-driven* means that tests and fixtures are executed by ``pytest-asyncio`` plugin. -This mode requires the simpliest tests and fixtures configuration and is +This mode requires the simplest tests and fixtures configuration and is recommended for default usage *unless* the same project and its test suite should execute tests from different async frameworks, e.g. ``asyncio`` and ``trio``. In this case, auto-handling can break tests designed for other framework; plase use *strict* From 63b45bf93d791610340980356c242d201ff43196 Mon Sep 17 00:00:00 2001 From: Andrew Svetlov Date: Sat, 8 Jan 2022 19:27:21 +0200 Subject: [PATCH 09/10] Apply suggestions from code review Co-authored-by: Michael Seifert --- README.rst | 2 +- pytest_asyncio/plugin.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.rst b/README.rst index 4a6a350b..b70b3200 100644 --- a/README.rst +++ b/README.rst @@ -236,7 +236,7 @@ Only test coroutines will be affected (by default, coroutines prefixed by """No marker!""" await asyncio.sleep(0, loop=event_loop) -In *auto* mode, the ``pytest.mark.asyncio`` marker can be omited, the merker is added +In *auto* mode, the ``pytest.mark.asyncio`` marker can be omitted, the marker is added automatically to *async* test functions. diff --git a/pytest_asyncio/plugin.py b/pytest_asyncio/plugin.py index 49a15999..44165602 100644 --- a/pytest_asyncio/plugin.py +++ b/pytest_asyncio/plugin.py @@ -26,7 +26,7 @@ class Mode(str, enum.Enum): LEGACY_ASYNCIO_FIXTURE = ( "'@pytest.fixture' is applied to {name} " "in 'legacy' mode, " - "please replace it with '@pytest_asyncio.pytest_asyncio' as a preparation " + "please replace it with '@pytest_asyncio.fixture' as a preparation " "for switching to 'strict' mode (or use 'auto' mode to seamlessly handle " "all these fixtures as asyncio-driven)." ) @@ -38,7 +38,7 @@ class Mode(str, enum.Enum): should be tested together, e.g. \ both pytest-asyncio and pytest-trio are used in the same project) 'legacy' - for keeping compatibility with pytest-asyncio<0.17: \ -auto-handling is disabled but asyncio_fixture usage is not enforced +auto-handling is disabled but pytest_asyncio.fixture usage is not enforced """ From 7fb70ed86f69101def8ec4d215f0ffbb3b1fcc39 Mon Sep 17 00:00:00 2001 From: Andrew Svetlov Date: Sat, 8 Jan 2022 19:33:43 +0200 Subject: [PATCH 10/10] Update tests/modes/test_legacy_mode.py Co-authored-by: Michael Seifert --- tests/modes/test_legacy_mode.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/modes/test_legacy_mode.py b/tests/modes/test_legacy_mode.py index 42c31eeb..df9c2cb6 100644 --- a/tests/modes/test_legacy_mode.py +++ b/tests/modes/test_legacy_mode.py @@ -12,7 +12,7 @@ LEGACY_ASYNCIO_FIXTURE = ( "'@pytest.fixture' is applied to {name} " "in 'legacy' mode, " - "please replace it with '@pytest_asyncio.pytest_asyncio' as a preparation " + "please replace it with '@pytest_asyncio.fixture' as a preparation " "for switching to 'strict' mode (or use 'auto' mode to seamlessly handle " "all these fixtures as asyncio-driven)." ).format(name="*")