From 8bf4d5d0654eb524635413443ba21523aeb23f36 Mon Sep 17 00:00:00 2001 From: Zac Hatfield-Dodds Date: Sun, 30 Oct 2022 01:11:23 -0700 Subject: [PATCH 1/8] Use ASCII dashes --- docs/source/quickstart.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/source/quickstart.rst b/docs/source/quickstart.rst index 0ef3164..490cc12 100644 --- a/docs/source/quickstart.rst +++ b/docs/source/quickstart.rst @@ -183,7 +183,7 @@ If you need to support Python 3.5, which doesn't allow ``yield`` inside an ``async def`` function, then you can define async fixtures using the `async_generator `__ -library – just make sure to put the ``@pytest.fixture`` *above* the +library - just make sure to put the ``@pytest.fixture`` *above* the ``@async_generator``. @@ -232,7 +232,7 @@ Here's a first attempt:: This will mostly work, but it has a few problems. The most obvious one is that when we run it, even if everything works perfectly, it will -hang at the end of the test – we never shut down the server, so the +hang at the end of the test - we never shut down the server, so the nursery block will wait forever for it to exit. To avoid this, we should cancel the nursery at the end of the test: @@ -292,9 +292,9 @@ you afterwards: Next problem: we have a race condition. We spawn a background task to call ``serve_tcp``, and then immediately try to connect to that server. Sometimes this will work fine. But it takes a little while for -the server to start up and be ready to accept connections – so other +the server to start up and be ready to accept connections - so other times, randomly, our connection attempt will happen too quickly, and -error out. After all – ``nursery.start_soon`` only promises that the +error out. After all - ``nursery.start_soon`` only promises that the task will be started *soon*, not that it has actually happened. So this test will be flaky, and flaky tests are the worst. @@ -378,7 +378,7 @@ Putting it all together: await echo_client.send_all(test_byte) assert await echo_client.receive_some(1) == test_byte -Now, this works – but there's still a lot of boilerplate. Remember, we +Now, this works - but there's still a lot of boilerplate. Remember, we need to write lots of tests for this server, and we don't want to have to copy-paste all that stuff into every test. Let's factor out the setup into a fixture:: From a071cfeb828e3c96cd5312a2db8617411abe5b78 Mon Sep 17 00:00:00 2001 From: Zac Hatfield-Dodds Date: Sun, 30 Oct 2022 01:11:23 -0700 Subject: [PATCH 2/8] Test on newer Python versions --- .github/workflows/ci.yml | 6 +++--- setup.py | 7 ++++++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9a68a8c..e9544ed 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,7 +13,7 @@ jobs: strategy: fail-fast: false matrix: - python: ['3.6', '3.7', '3.8', '3.9'] + python: ['3.7', '3.8', '3.9', '3.10', '3.11'] steps: - name: Checkout uses: actions/checkout@v2 @@ -35,7 +35,7 @@ jobs: strategy: fail-fast: false matrix: - python: ['pypy-3.6', '3.6', '3.7', '3.8', '3.9', '3.8-dev', '3.9-dev'] + python: ['pypy-3.7', '3.7', 'pypy-3.8', '3.8', 'pypy-3.9', '3.9', '3.10', '3.11'] check_formatting: ['0'] check_docs: ['0'] extra_name: [''] @@ -74,7 +74,7 @@ jobs: strategy: fail-fast: false matrix: - python: ['3.6', '3.7', '3.8', '3.9'] + python: ['3.7', '3.8', '3.9', '3.10', '3.11'] steps: - name: Checkout uses: actions/checkout@v2 diff --git a/setup.py b/setup.py index 054ffca..1666d5f 100644 --- a/setup.py +++ b/setup.py @@ -28,7 +28,7 @@ 'testing', 'trio', ], - python_requires=">=3.6", + python_requires=">=3.7", classifiers=[ "License :: OSI Approved :: MIT License", "License :: OSI Approved :: Apache Software License", @@ -36,6 +36,11 @@ "Operating System :: MacOS :: MacOS X", "Operating System :: Microsoft :: Windows", "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Topic :: System :: Networking", From 222f6ff056edd4c746bf4529a4153067aa807d84 Mon Sep 17 00:00:00 2001 From: Zac Hatfield-Dodds Date: Sun, 30 Oct 2022 01:11:23 -0700 Subject: [PATCH 3/8] Update dependencies --- docs-requirements.in | 8 ++--- docs-requirements.txt | 78 ++++++++++++++++++++++++------------------- docs/source/conf.py | 2 +- setup.py | 7 ++-- test-requirements.txt | 6 ++-- 5 files changed, 54 insertions(+), 47 deletions(-) diff --git a/docs-requirements.in b/docs-requirements.in index 4b299a1..4e295c0 100644 --- a/docs-requirements.in +++ b/docs-requirements.in @@ -1,4 +1,3 @@ -# RTD is currently installing 1.5.3, which has a bug in :lineno-match: sphinx >= 1.6.1 sphinx_rtd_theme sphinxcontrib-trio @@ -10,8 +9,7 @@ attrs >= 17.4.0 towncrier != 19.9.0,!= 21.3.0 # pytest-trio's own dependencies -trio >= 0.15.0 +trio >= 0.22.0 async_generator >= 1.9 -outcome -# For node.get_closest_marker -pytest >= 3.6 +outcome >= 1.1.0 +pytest >= 7.2.0 diff --git a/docs-requirements.txt b/docs-requirements.txt index b401bbf..b81aba4 100644 --- a/docs-requirements.txt +++ b/docs-requirements.txt @@ -1,5 +1,5 @@ # -# This file is autogenerated by pip-compile +# This file is autogenerated by pip-compile with python 3.8 # To update, run: # # pip-compile docs-requirements.in @@ -10,99 +10,109 @@ async-generator==1.10 # via # -r docs-requirements.in # trio -attrs==20.3.0 +attrs==22.1.0 # via # -r docs-requirements.in # outcome # pytest # trio -babel==2.9.0 +babel==2.10.3 # via sphinx -certifi==2020.12.5 +certifi==2022.9.24 # via requests -chardet==4.0.0 +charset-normalizer==2.1.1 # via requests -click==7.1.2 +click==8.1.3 + # via + # click-default-group + # towncrier +click-default-group==1.2.2 # via towncrier -docutils==0.16 +docutils==0.17.1 # via # sphinx # sphinx-rtd-theme -idna==2.10 +exceptiongroup==1.0.0 + # via + # pytest + # trio +idna==3.4 # via # requests # trio -imagesize==1.2.0 +imagesize==1.4.1 # via sphinx -incremental==21.3.0 +importlib-metadata==5.0.0 + # via sphinx +incremental==22.10.0 # via towncrier iniconfig==1.1.1 # via pytest -jinja2==2.11.3 +jinja2==3.1.2 # via # sphinx # towncrier -markupsafe==1.1.1 +markupsafe==2.1.1 # via jinja2 -outcome==1.1.0 +outcome==1.2.0 # via # -r docs-requirements.in # trio -packaging==20.9 +packaging==21.3 # via # pytest # sphinx -pluggy==0.13.1 - # via pytest -py==1.10.0 +pluggy==1.0.0 # via pytest -pygments==2.8.1 +pygments==2.13.0 # via sphinx -pyparsing==2.4.7 +pyparsing==3.0.9 # via packaging -pytest==6.2.3 +pytest==7.2.0 # via -r docs-requirements.in -pytz==2021.1 +pytz==2022.5 # via babel -requests==2.25.1 +requests==2.28.1 # via sphinx -sniffio==1.2.0 +sniffio==1.3.0 # via trio -snowballstemmer==2.1.0 +snowballstemmer==2.2.0 # via sphinx -sortedcontainers==2.3.0 +sortedcontainers==2.4.0 # via trio -sphinx-rtd-theme==0.5.2 - # via -r docs-requirements.in -sphinx==3.5.4 +sphinx==5.3.0 # via # -r docs-requirements.in # sphinx-rtd-theme # sphinxcontrib-trio +sphinx-rtd-theme==1.0.0 + # via -r docs-requirements.in sphinxcontrib-applehelp==1.0.2 # via sphinx sphinxcontrib-devhelp==1.0.2 # via sphinx -sphinxcontrib-htmlhelp==1.0.3 +sphinxcontrib-htmlhelp==2.0.0 # via sphinx sphinxcontrib-jsmath==1.0.1 # via sphinx sphinxcontrib-qthelp==1.0.3 # via sphinx -sphinxcontrib-serializinghtml==1.1.4 +sphinxcontrib-serializinghtml==1.1.5 # via sphinx sphinxcontrib-trio==1.1.2 # via -r docs-requirements.in -toml==0.10.2 +tomli==2.0.1 # via # pytest # towncrier -towncrier==19.2.0 +towncrier==22.8.0 # via -r docs-requirements.in -trio==0.18.0 +trio==0.22.0 # via -r docs-requirements.in -urllib3==1.26.4 +urllib3==1.26.12 # via requests +zipp==3.10.0 + # via importlib-metadata # The following packages are considered to be unsafe in a requirements file: # setuptools diff --git a/docs/source/conf.py b/docs/source/conf.py index 70282d8..4295707 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -109,7 +109,7 @@ def setup(app): # # This is also used if you do content translation via gettext catalogs. # Usually you set "language" from the command line for these cases. -language = None +language = "en" # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. diff --git a/setup.py b/setup.py index 1666d5f..b79a918 100644 --- a/setup.py +++ b/setup.py @@ -16,11 +16,10 @@ packages=find_packages(), entry_points={'pytest11': ['trio = pytest_trio.plugin']}, install_requires=[ - "trio >= 0.15.0", + "trio >= 0.22.0", # for ExceptionGroup support "async_generator >= 1.9", - "outcome", - # For node.get_closest_marker - "pytest >= 3.6" + "outcome >= 1.1.0", + "pytest >= 7.2.0", # for ExceptionGroup support ], keywords=[ 'async', diff --git a/test-requirements.txt b/test-requirements.txt index c8280fc..b1d1509 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,3 +1,3 @@ -pytest==6.1.2 -pytest-cov==2.10.1 -hypothesis==5.47.0 +pytest==7.2.0 +pytest-cov==4.0.0 +hypothesis==6.56.4 From f338c591fff6ddf75b288dd17cd6d42e6851f620 Mon Sep 17 00:00:00 2001 From: Zac Hatfield-Dodds Date: Sun, 30 Oct 2022 01:11:24 -0700 Subject: [PATCH 4/8] Improve too-many-Clocks message --- pytest_trio/plugin.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pytest_trio/plugin.py b/pytest_trio/plugin.py index 8ddb107..986ee52 100644 --- a/pytest_trio/plugin.py +++ b/pytest_trio/plugin.py @@ -343,13 +343,13 @@ def decorator(fn): @wraps(fn) def wrapper(**kwargs): __tracebackhide__ = True - clocks = [c for c in kwargs.values() if isinstance(c, Clock)] + clocks = {k: c for k, c in kwargs.items() if isinstance(c, Clock)} if not clocks: clock = None elif len(clocks) == 1: - clock = clocks[0] + clock = list(clocks.values())[0] else: - raise ValueError("too many clocks spoil the broth!") + raise ValueError(f"Expected at most one Clock in kwargs, got {clocks!r}") instruments = [ i for i in kwargs.values() if isinstance(i, Instrument) ] From 66188cb0ae548db7b9df2d4dfc92d441a1def1c1 Mon Sep 17 00:00:00 2001 From: Zac Hatfield-Dodds Date: Sun, 30 Oct 2022 01:11:24 -0700 Subject: [PATCH 5/8] Switch from YAPF to Black --- .style.yapf | 180 ------------------ CHEATSHEET.rst | 10 +- MANIFEST.in | 2 +- ci.sh | 11 +- docs/source/conf.py | 69 +++---- pytest_trio/_tests/helpers.py | 9 +- pytest_trio/_tests/test_async_fixture.py | 2 +- .../_tests/test_async_yield_fixture.py | 24 +-- pytest_trio/_tests/test_basic.py | 2 +- pytest_trio/_tests/test_fixture_mistakes.py | 12 +- pytest_trio/_tests/test_fixture_nursery.py | 4 +- pytest_trio/_tests/test_fixture_ordering.py | 8 +- .../_tests/test_hypothesis_interaction.py | 7 +- pytest_trio/_tests/test_sync_fixture.py | 8 +- pytest_trio/_tests/test_trio_mode.py | 12 +- pytest_trio/plugin.py | 65 +++---- setup.py | 10 +- 17 files changed, 110 insertions(+), 325 deletions(-) delete mode 100644 .style.yapf diff --git a/.style.yapf b/.style.yapf deleted file mode 100644 index 2c71c9d..0000000 --- a/.style.yapf +++ /dev/null @@ -1,180 +0,0 @@ -[style] -# Align closing bracket with visual indentation. -align_closing_bracket_with_visual_indent=True - -# Allow dictionary keys to exist on multiple lines. For example: -# -# x = { -# ('this is the first element of a tuple', -# 'this is the second element of a tuple'): -# value, -# } -allow_multiline_dictionary_keys=False - -# Allow lambdas to be formatted on more than one line. -allow_multiline_lambdas=False - -# Insert a blank line before a class-level docstring. -blank_line_before_class_docstring=False - -# Insert a blank line before a 'def' or 'class' immediately nested -# within another 'def' or 'class'. For example: -# -# class Foo: -# # <------ this blank line -# def method(): -# ... -blank_line_before_nested_class_or_def=False - -# Do not split consecutive brackets. Only relevant when -# dedent_closing_brackets is set. For example: -# -# call_func_that_takes_a_dict( -# { -# 'key1': 'value1', -# 'key2': 'value2', -# } -# ) -# -# would reformat to: -# -# call_func_that_takes_a_dict({ -# 'key1': 'value1', -# 'key2': 'value2', -# }) -coalesce_brackets=False - -# The column limit. -column_limit=79 - -# Indent width used for line continuations. -continuation_indent_width=4 - -# Put closing brackets on a separate line, dedented, if the bracketed -# expression can't fit in a single line. Applies to all kinds of brackets, -# including function definitions and calls. For example: -# -# config = { -# 'key1': 'value1', -# 'key2': 'value2', -# } # <--- this bracket is dedented and on a separate line -# -# time_series = self.remote_client.query_entity_counters( -# entity='dev3246.region1', -# key='dns.query_latency_tcp', -# transform=Transformation.AVERAGE(window=timedelta(seconds=60)), -# start_ts=now()-timedelta(days=3), -# end_ts=now(), -# ) # <--- this bracket is dedented and on a separate line -dedent_closing_brackets=True - -# Place each dictionary entry onto its own line. -each_dict_entry_on_separate_line=True - -# The regex for an i18n comment. The presence of this comment stops -# reformatting of that line, because the comments are required to be -# next to the string they translate. -i18n_comment= - -# The i18n function call names. The presence of this function stops -# reformattting on that line, because the string it has cannot be moved -# away from the i18n comment. -i18n_function_call= - -# Indent the dictionary value if it cannot fit on the same line as the -# dictionary key. For example: -# -# config = { -# 'key1': -# 'value1', -# 'key2': value1 + -# value2, -# } -indent_dictionary_value=True - -# The number of columns to use for indentation. -indent_width=4 - -# Join short lines into one line. E.g., single line 'if' statements. -join_multiple_lines=False - -# Use spaces around default or named assigns. -spaces_around_default_or_named_assign=False - -# Use spaces around the power operator. -spaces_around_power_operator=False - -# The number of spaces required before a trailing comment. -spaces_before_comment=2 - -# Insert a space between the ending comma and closing bracket of a list, -# etc. -space_between_ending_comma_and_closing_bracket=False - -# Split before arguments if the argument list is terminated by a -# comma. -split_arguments_when_comma_terminated=True - -# Set to True to prefer splitting before '&', '|' or '^' rather than -# after. -split_before_bitwise_operator=True - -# Split before a dictionary or set generator (comp_for). For example, note -# the split before the 'for': -# -# foo = { -# variable: 'Hello world, have a nice day!' -# for variable in bar if variable != 42 -# } -split_before_dict_set_generator=True - -# If an argument / parameter list is going to be split, then split before -# the first argument. -split_before_first_argument=True - -# Set to True to prefer splitting before 'and' or 'or' rather than -# after. -split_before_logical_operator=True - -# Split named assignments onto individual lines. -split_before_named_assigns=True - -# The penalty for splitting right after the opening bracket. -split_penalty_after_opening_bracket=30 - -# The penalty for splitting the line after a unary operator. -split_penalty_after_unary_operator=10000 - -# The penalty for splitting right before an if expression. -split_penalty_before_if_expr=0 - -# The penalty of splitting the line around the '&', '|', and '^' -# operators. -split_penalty_bitwise_operator=300 - -# The penalty for characters over the column limit. -split_penalty_excess_character=4500 - -# The penalty incurred by adding a line split to the unwrapped line. The -# more line splits added the higher the penalty. -split_penalty_for_added_line_split=30 - -# The penalty of splitting a list of "import as" names. For example: -# -# from a_very_long_or_indented_module_name_yada_yad import (long_argument_1, -# long_argument_2, -# long_argument_3) -# -# would reformat to something like: -# -# from a_very_long_or_indented_module_name_yada_yad import ( -# long_argument_1, long_argument_2, long_argument_3) -split_penalty_import_names=0 - -# The penalty of splitting the line around the 'and' and 'or' -# operators. -split_penalty_logical_operator=0 - -# Use the Tab character for indentation. -use_tabs=False - diff --git a/CHEATSHEET.rst b/CHEATSHEET.rst index 49a8b8d..aeacf0a 100644 --- a/CHEATSHEET.rst +++ b/CHEATSHEET.rst @@ -9,15 +9,7 @@ To run tests * Actually run the tests: ``pytest pytest_trio`` - -To run yapf ------------ - -* Show what changes yapf wants to make: ``yapf -rpd setup.py - pytest_trio`` - -* Apply all changes directly to the source tree: ``yapf -rpi setup.py - pytest_trio`` +* Format the code with ``black .`` To make a release diff --git a/MANIFEST.in b/MANIFEST.in index 4edd4b1..afc90e2 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,5 +1,5 @@ include README.rst CHEATSHEET.rst LICENSE* CODE_OF_CONDUCT* CONTRIBUTING* -include .coveragerc .style.yapf +include .coveragerc include test-requirements.txt recursive-include docs * prune docs/build diff --git a/ci.sh b/ci.sh index ddcd21f..aae8b3c 100755 --- a/ci.sh +++ b/ci.sh @@ -6,9 +6,6 @@ set -ex -o pipefail uname -a env | sort -# See https://github.com/python-trio/trio/issues/334 -YAPF_VERSION=0.22.0 - # Curl's built-in retry system is not very robust; it gives up on lots of # network errors that we want to retry on. Wget might work better, but it's # not installed on azure pipelines's windows boxes. So... let's try some good @@ -33,16 +30,16 @@ python setup.py sdist --formats=zip python -m pip install dist/*.zip if [ "$CHECK_FORMATTING" = "1" ]; then - pip install yapf==${YAPF_VERSION} - if ! yapf -rpd setup.py pytest_trio; then + pip install black + if ! black --check . ; then cat <=36', 'async_generator']) +@pytest.fixture(params=["Python>=36", "async_generator"]) def async_yield_implementation(request): - if request.param == 'Python>=36': + if request.param == "Python>=36": def patch_code(code): # Convert code to use Python>=3.6 builtin async generator - code = re.sub(r'(?m)^\s*@async_generator\n', r'', code) - code = re.sub(r'await yield_', r'yield', code) + code = re.sub(r"(?m)^\s*@async_generator\n", r"", code) + code = re.sub(r"await yield_", r"yield", code) return code return patch_code @@ -121,9 +121,7 @@ def test_after(): result.assert_outcomes(passed=3) -def test_async_yield_fixture_within_sync_fixture( - testdir, async_yield_implementation -): +def test_async_yield_fixture_within_sync_fixture(testdir, async_yield_implementation): testdir.makepyfile( async_yield_implementation( @@ -174,7 +172,7 @@ def test_after(): def test_async_yield_fixture_within_sync_yield_fixture( - testdir, async_yield_implementation + testdir, async_yield_implementation ): testdir.makepyfile( @@ -230,9 +228,7 @@ def test_after(): result.assert_outcomes(passed=3) -def test_async_yield_fixture_with_multiple_yields( - testdir, async_yield_implementation -): +def test_async_yield_fixture_with_multiple_yields(testdir, async_yield_implementation): testdir.makepyfile( async_yield_implementation( @@ -304,7 +300,7 @@ async def test_actual_test(server): def test_async_yield_fixture_crashed_teardown_allow_other_teardowns( - testdir, async_yield_implementation + testdir, async_yield_implementation ): testdir.makepyfile( @@ -358,6 +354,4 @@ def test_after(): result = testdir.runpytest() result.assert_outcomes(failed=1, passed=2) - result.stdout.re_match_lines( - [r'E\W+RuntimeError: Crash during fixture teardown'] - ) + result.stdout.re_match_lines([r"E\W+RuntimeError: Crash during fixture teardown"]) diff --git a/pytest_trio/_tests/test_basic.py b/pytest_trio/_tests/test_basic.py index c687d53..65dd911 100644 --- a/pytest_trio/_tests/test_basic.py +++ b/pytest_trio/_tests/test_basic.py @@ -58,7 +58,7 @@ def test_check_async_test_called(): result.assert_outcomes(passed=2) -@pytest.mark.xfail(reason='Raises pytest internal error so far...') +@pytest.mark.xfail(reason="Raises pytest internal error so far...") def test_sync_function_with_trio_mark(testdir): testdir.makepyfile( diff --git a/pytest_trio/_tests/test_fixture_mistakes.py b/pytest_trio/_tests/test_fixture_mistakes.py index 077861d..b00de9f 100644 --- a/pytest_trio/_tests/test_fixture_mistakes.py +++ b/pytest_trio/_tests/test_fixture_mistakes.py @@ -35,9 +35,7 @@ def test_sync_indirect(indirect_trio_time): result = testdir.runpytest() result.assert_outcomes(passed=1, errors=2) - result.stdout.fnmatch_lines( - ["*: Trio fixtures can only be used by Trio tests*"] - ) + result.stdout.fnmatch_lines(["*: Trio fixtures can only be used by Trio tests*"]) def test_trio_fixture_with_wrong_scope_without_trio_mode(testdir): @@ -114,9 +112,7 @@ def test_whatever(async_fixture): result = testdir.runpytest() result.assert_outcomes(errors=1) - result.stdout.fnmatch_lines( - ["*: Trio fixtures can only be used by Trio tests*"] - ) + result.stdout.fnmatch_lines(["*: Trio fixtures can only be used by Trio tests*"]) @enable_trio_mode @@ -168,6 +164,4 @@ async def test_whatever(mock_clock, extra_clock): result = testdir.runpytest() result.assert_outcomes(failed=1) - result.stdout.fnmatch_lines( - ["*ValueError: too many clocks spoil the broth!*"] - ) + result.stdout.fnmatch_lines(["*ValueError: too many clocks spoil the broth!*"]) diff --git a/pytest_trio/_tests/test_fixture_nursery.py b/pytest_trio/_tests/test_fixture_nursery.py index 7719fa1..503ad5e 100644 --- a/pytest_trio/_tests/test_fixture_nursery.py +++ b/pytest_trio/_tests/test_fixture_nursery.py @@ -17,6 +17,6 @@ async def server(nursery): @pytest.mark.trio async def test_try(server): stream = await trio.testing.open_stream_to_socket_listener(server) - await stream.send_all(b'ping') + await stream.send_all(b"ping") rep = await stream.receive_some(4) - assert rep == b'ping' + assert rep == b"ping" diff --git a/pytest_trio/_tests/test_fixture_ordering.py b/pytest_trio/_tests/test_fixture_ordering.py index 8af1cdb..c892cd8 100644 --- a/pytest_trio/_tests/test_fixture_ordering.py +++ b/pytest_trio/_tests/test_fixture_ordering.py @@ -283,7 +283,9 @@ def test_post(): "userfix": float("inf"), } assert final_time == 1 - """.replace("CRASHYFIX_HERE", crashyfix) + """.replace( + "CRASHYFIX_HERE", crashyfix + ) ) result = testdir.runpytest() @@ -329,9 +331,7 @@ async def test_try(fixture): result = testdir.runpytest() result.assert_outcomes(passed=0, failed=1) - result.stdout.fnmatch_lines_random([ - "*OOPS*", - ]) + result.stdout.fnmatch_lines_random(["*OOPS*"]) # Makes sure that diff --git a/pytest_trio/_tests/test_hypothesis_interaction.py b/pytest_trio/_tests/test_hypothesis_interaction.py index 30a37db..75aa9f7 100644 --- a/pytest_trio/_tests/test_hypothesis_interaction.py +++ b/pytest_trio/_tests/test_hypothesis_interaction.py @@ -1,8 +1,9 @@ import pytest import trio from trio.tests.test_scheduler_determinism import ( - scheduler_trace, test_the_trio_scheduler_is_not_deterministic, - test_the_trio_scheduler_is_deterministic_if_seeded + scheduler_trace, + test_the_trio_scheduler_is_not_deterministic, + test_the_trio_scheduler_is_deterministic_if_seeded, ) from hypothesis import given, settings, strategies as st @@ -29,7 +30,7 @@ async def test_mark_outer(n): @our_settings -@pytest.mark.parametrize('y', [1, 2]) +@pytest.mark.parametrize("y", [1, 2]) @given(x=st.none()) @pytest.mark.trio async def test_mark_and_parametrize(x, y): diff --git a/pytest_trio/_tests/test_sync_fixture.py b/pytest_trio/_tests/test_sync_fixture.py index 7a4cb0f..508b2f0 100644 --- a/pytest_trio/_tests/test_sync_fixture.py +++ b/pytest_trio/_tests/test_sync_fixture.py @@ -3,12 +3,12 @@ @pytest.fixture def sync_fix(): - return 'sync_fix' + return "sync_fix" @pytest.mark.trio async def test_single_sync_fixture(sync_fix): - assert sync_fix == 'sync_fix' + assert sync_fix == "sync_fix" def test_single_yield_fixture(testdir): @@ -139,6 +139,4 @@ def test_after(): result = testdir.runpytest() result.assert_outcomes(failed=1, passed=2) - result.stdout.re_match_lines( - [r'E\W+RuntimeError: Crash during fixture teardown'] - ) + result.stdout.re_match_lines([r"E\W+RuntimeError: Crash during fixture teardown"]) diff --git a/pytest_trio/_tests/test_trio_mode.py b/pytest_trio/_tests/test_trio_mode.py index f7bf61f..19efdc1 100644 --- a/pytest_trio/_tests/test_trio_mode.py +++ b/pytest_trio/_tests/test_trio_mode.py @@ -56,9 +56,7 @@ def run(*args, **kwargs): def test_trio_mode_and_qtrio_run_configuration(testdir): - testdir.makefile( - ".ini", pytest="[pytest]\ntrio_mode = true\ntrio_run = qtrio\n" - ) + testdir.makefile(".ini", pytest="[pytest]\ntrio_mode = true\ntrio_run = qtrio\n") testdir.makepyfile(qtrio=qtrio_text) @@ -141,9 +139,7 @@ async def test(): def test_closest_explicit_run_wins(testdir): - testdir.makefile( - ".ini", pytest=f"[pytest]\ntrio_mode = true\ntrio_run = trio\n" - ) + testdir.makefile(".ini", pytest=f"[pytest]\ntrio_mode = true\ntrio_run = trio\n") testdir.makepyfile(qtrio=qtrio_text) test_text = """ @@ -163,9 +159,7 @@ async def test(): def test_ini_run_wins_with_blank_marker(testdir): - testdir.makefile( - ".ini", pytest=f"[pytest]\ntrio_mode = true\ntrio_run = qtrio\n" - ) + testdir.makefile(".ini", pytest=f"[pytest]\ntrio_mode = true\ntrio_run = qtrio\n") testdir.makepyfile(qtrio=qtrio_text) test_text = """ diff --git a/pytest_trio/plugin.py b/pytest_trio/plugin.py index 986ee52..bcb6528 100644 --- a/pytest_trio/plugin.py +++ b/pytest_trio/plugin.py @@ -11,8 +11,11 @@ from trio.abc import Clock, Instrument from trio.testing import MockClock from async_generator import ( - async_generator, yield_, asynccontextmanager, isasyncgen, - isasyncgenfunction + async_generator, + yield_, + asynccontextmanager, + isasyncgen, + isasyncgenfunction, ) ################################################################ @@ -51,9 +54,8 @@ def pytest_addoption(parser): def pytest_configure(config): # So that it shows up in 'pytest --markers' output: config.addinivalue_line( - "markers", "trio: " - "mark the test as an async trio test; " - "it will be run using trio.run" + "markers", + "trio: mark the test as an async trio test; it will be run using trio.run", ) @@ -61,7 +63,7 @@ def pytest_configure(config): def pytest_exception_interact(node, call, report): if issubclass(call.excinfo.type, trio.MultiError): # TODO: not really elegant (pytest cannot output color with this hack) - report.longrepr = ''.join(format_exception(*call.excinfo._excinfo)) + report.longrepr = "".join(format_exception(*call.excinfo._excinfo)) ################################################################ @@ -349,13 +351,11 @@ def wrapper(**kwargs): elif len(clocks) == 1: clock = list(clocks.values())[0] else: - raise ValueError(f"Expected at most one Clock in kwargs, got {clocks!r}") - instruments = [ - i for i in kwargs.values() if isinstance(i, Instrument) - ] - return run( - partial(fn, **kwargs), clock=clock, instruments=instruments - ) + raise ValueError( + f"Expected at most one Clock in kwargs, got {clocks!r}" + ) + instruments = [i for i in kwargs.values() if isinstance(i, Instrument)] + return run(partial(fn, **kwargs), clock=clock, instruments=instruments) return wrapper @@ -369,7 +369,7 @@ def _trio_test_runner_factory(item, testfunc=None): testfunc = item.obj for marker in item.iter_markers("trio"): - maybe_run = marker.kwargs.get('run') + maybe_run = marker.kwargs.get("run") if maybe_run is not None: run = maybe_run break @@ -377,15 +377,13 @@ def _trio_test_runner_factory(item, testfunc=None): # no marker found that explicitly specifiers the runner so use config run = choose_run(config=item.config) - if getattr(testfunc, '_trio_test_runner_wrapped', False): + if getattr(testfunc, "_trio_test_runner_wrapped", False): # We have already wrapped this, perhaps because we combined Hypothesis # with pytest.mark.parametrize return testfunc if not iscoroutinefunction(testfunc): - pytest.fail( - 'test function `%r` is marked trio but is not async' % item - ) + pytest.fail("test function `%r` is marked trio but is not async" % item) @_trio_test(run=run) async def _bootstrap_fixtures_and_run_test(**kwargs): @@ -393,10 +391,7 @@ async def _bootstrap_fixtures_and_run_test(**kwargs): test_ctx = TrioTestContext() test = TrioFixture( - "".format(testfunc.__name__), - testfunc, - kwargs, - is_test=True + "".format(testfunc.__name__), testfunc, kwargs, is_test=True ) contextvars_ctx = contextvars.copy_context() @@ -435,16 +430,15 @@ async def _bootstrap_fixtures_and_run_test(**kwargs): @pytest.hookimpl(hookwrapper=True) def pytest_runtest_call(item): if item.get_closest_marker("trio") is not None: - if hasattr(item.obj, 'hypothesis'): + if hasattr(item.obj, "hypothesis"): # If it's a Hypothesis test, we go in a layer. item.obj.hypothesis.inner_test = _trio_test_runner_factory( item, item.obj.hypothesis.inner_test ) - elif getattr(item.obj, 'is_hypothesis_test', - False): # pragma: no cover + elif getattr(item.obj, "is_hypothesis_test", False): # pragma: no cover pytest.fail( - 'test function `%r` is using Hypothesis, but pytest-trio ' - 'only works with Hypothesis 3.64.0 or later.' % item + "test function `%r` is using Hypothesis, but pytest-trio " + "only works with Hypothesis 3.64.0 or later." % item ) else: item.obj = _trio_test_runner_factory(item) @@ -463,8 +457,7 @@ def trio_fixture(func): def _is_trio_fixture(func, coerce_async, kwargs): if getattr(func, "_force_trio_fixture", False): return True - if (coerce_async and - (iscoroutinefunction(func) or isasyncgenfunction(func))): + if coerce_async and (iscoroutinefunction(func) or isasyncgenfunction(func)): return True if any(isinstance(value, TrioFixture) for value in kwargs.values()): return True @@ -472,16 +465,13 @@ def _is_trio_fixture(func, coerce_async, kwargs): def handle_fixture(fixturedef, request, force_trio_mode): - is_trio_test = (request.node.get_closest_marker("trio") is not None) + is_trio_test = request.node.get_closest_marker("trio") is not None if force_trio_mode: is_trio_mode = True else: is_trio_mode = request.node.config.getini("trio_mode") - coerce_async = (is_trio_test or is_trio_mode) - kwargs = { - name: request.getfixturevalue(name) - for name in fixturedef.argnames - } + coerce_async = is_trio_test or is_trio_mode + kwargs = {name: request.getfixturevalue(name) for name in fixturedef.argnames} if _is_trio_fixture(fixturedef.func, coerce_async, kwargs): if request.scope != "function": raise RuntimeError("Trio fixtures must be function-scope") @@ -522,11 +512,12 @@ def choose_run(config): run = trio.run elif run_string == "qtrio": import qtrio + run = qtrio.run else: raise ValueError( - f"{run_string!r} not valid for 'trio_run' config." + - " Must be one of: trio, qtrio" + f"{run_string!r} not valid for 'trio_run' config." + + " Must be one of: trio, qtrio" ) return run diff --git a/setup.py b/setup.py index b79a918..7d1f956 100644 --- a/setup.py +++ b/setup.py @@ -14,7 +14,7 @@ author_email="emmanuel.leblond@gmail.com", license="MIT -or- Apache License 2.0", packages=find_packages(), - entry_points={'pytest11': ['trio = pytest_trio.plugin']}, + entry_points={"pytest11": ["trio = pytest_trio.plugin"]}, install_requires=[ "trio >= 0.22.0", # for ExceptionGroup support "async_generator >= 1.9", @@ -22,10 +22,10 @@ "pytest >= 7.2.0", # for ExceptionGroup support ], keywords=[ - 'async', - 'pytest', - 'testing', - 'trio', + "async", + "pytest", + "testing", + "trio", ], python_requires=">=3.7", classifiers=[ From 4c2a82f5499cbde7ba041bab4eab16d80bd25350 Mon Sep 17 00:00:00 2001 From: Zac Hatfield-Dodds Date: Sun, 30 Oct 2022 01:11:24 -0700 Subject: [PATCH 6/8] Drop dependency on async_generator --- docs-requirements.in | 1 - docs-requirements.txt | 4 +- docs/source/quickstart.rst | 18 ---- pytest.ini | 4 +- .../_tests/test_async_yield_fixture.py | 102 +++++------------- pytest_trio/_tests/test_fixture_mistakes.py | 8 +- pytest_trio/_tests/test_fixture_ordering.py | 29 ++--- pytest_trio/plugin.py | 14 +-- setup.py | 1 - 9 files changed, 43 insertions(+), 138 deletions(-) diff --git a/docs-requirements.in b/docs-requirements.in index 4e295c0..4acf894 100644 --- a/docs-requirements.in +++ b/docs-requirements.in @@ -10,6 +10,5 @@ towncrier != 19.9.0,!= 21.3.0 # pytest-trio's own dependencies trio >= 0.22.0 -async_generator >= 1.9 outcome >= 1.1.0 pytest >= 7.2.0 diff --git a/docs-requirements.txt b/docs-requirements.txt index b81aba4..ae0c01d 100644 --- a/docs-requirements.txt +++ b/docs-requirements.txt @@ -7,9 +7,7 @@ alabaster==0.7.12 # via sphinx async-generator==1.10 - # via - # -r docs-requirements.in - # trio + # via trio attrs==22.1.0 # via # -r docs-requirements.in diff --git a/docs/source/quickstart.rst b/docs/source/quickstart.rst index 490cc12..fe23cd1 100644 --- a/docs/source/quickstart.rst +++ b/docs/source/quickstart.rst @@ -93,17 +93,6 @@ And we're done! Let's try running pytest again: ============================== FAILURES ============================== __________________________ test_should_fail __________________________ - value = - - async def yield_(value=None): - > return await _yield_(value) - - venv/lib/python3.8/site-packages/async_generator/_impl.py:106: - _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ - venv/lib/python3.8/site-packages/async_generator/_impl.py:99: in _yield_ - return (yield _wrap(value)) - _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ - async def test_should_fail(): > assert False E assert False @@ -179,13 +168,6 @@ regular pytest fixture:: # Teardown code, executed after the test is done await connection.execute("ROLLBACK") -If you need to support Python 3.5, which doesn't allow ``yield`` -inside an ``async def`` function, then you can define async fixtures -using the `async_generator -`__ -library - just make sure to put the ``@pytest.fixture`` *above* the -``@async_generator``. - .. _server-fixture-example: diff --git a/pytest.ini b/pytest.ini index e7e9beb..54951e1 100644 --- a/pytest.ini +++ b/pytest.ini @@ -1,2 +1,2 @@ -[pytest] -addopts = -W error -ra -v --pyargs pytest_trio --verbose --cov +[pytest] +addopts = -W error -ra -v --pyargs pytest_trio --verbose --cov diff --git a/pytest_trio/_tests/test_async_yield_fixture.py b/pytest_trio/_tests/test_async_yield_fixture.py index 6eee232..58d1a55 100644 --- a/pytest_trio/_tests/test_async_yield_fixture.py +++ b/pytest_trio/_tests/test_async_yield_fixture.py @@ -1,40 +1,17 @@ -import sys -import pytest -import re - - -@pytest.fixture(params=["Python>=36", "async_generator"]) -def async_yield_implementation(request): - if request.param == "Python>=36": - - def patch_code(code): - # Convert code to use Python>=3.6 builtin async generator - code = re.sub(r"(?m)^\s*@async_generator\n", r"", code) - code = re.sub(r"await yield_", r"yield", code) - return code - - return patch_code - else: - return lambda x: x - - -def test_single_async_yield_fixture(testdir, async_yield_implementation): +def test_single_async_yield_fixture(testdir): testdir.makepyfile( - async_yield_implementation( - """ + """ import pytest import trio - from async_generator import async_generator, yield_ events = [] @pytest.fixture - @async_generator async def fix1(): events.append('fix1 setup') await trio.sleep(0) - await yield_('fix1') + yield 'fix1' await trio.sleep(0) events.append('fix1 teardown') @@ -53,7 +30,6 @@ def test_after(): 'fix1 teardown', ] """ - ) ) result = testdir.runpytest() @@ -61,35 +37,31 @@ def test_after(): result.assert_outcomes(passed=3) -def test_nested_async_yield_fixture(testdir, async_yield_implementation): +def test_nested_async_yield_fixture(testdir): testdir.makepyfile( - async_yield_implementation( - """ + """ import pytest import trio - from async_generator import async_generator, yield_ events = [] @pytest.fixture - @async_generator async def fix2(): events.append('fix2 setup') await trio.sleep(0) - await yield_('fix2') + yield 'fix2' await trio.sleep(0) events.append('fix2 teardown') @pytest.fixture - @async_generator async def fix1(fix2): events.append('fix1 setup') await trio.sleep(0) - await yield_('fix1') + yield 'fix1' await trio.sleep(0) events.append('fix1 teardown') @@ -113,7 +85,6 @@ def test_after(): 'fix2 teardown', ] """ - ) ) result = testdir.runpytest() @@ -121,24 +92,21 @@ def test_after(): result.assert_outcomes(passed=3) -def test_async_yield_fixture_within_sync_fixture(testdir, async_yield_implementation): +def test_async_yield_fixture_within_sync_fixture(testdir): testdir.makepyfile( - async_yield_implementation( - """ + """ import pytest import trio - from async_generator import async_generator, yield_ events = [] @pytest.fixture - @async_generator async def fix2(): events.append('fix2 setup') await trio.sleep(0) - await yield_('fix2') + yield 'fix2' await trio.sleep(0) events.append('fix2 teardown') @@ -163,7 +131,6 @@ def test_after(): 'fix2 teardown', ] """ - ) ) result = testdir.runpytest() @@ -171,26 +138,21 @@ def test_after(): result.assert_outcomes(passed=3) -def test_async_yield_fixture_within_sync_yield_fixture( - testdir, async_yield_implementation -): +def test_async_yield_fixture_within_sync_yield_fixture(testdir): testdir.makepyfile( - async_yield_implementation( - """ + """ import pytest import trio - from async_generator import async_generator, yield_ events = [] @pytest.fixture - @async_generator async def fix2(): events.append('fix2 setup') await trio.sleep(0) - await yield_('fix2') + yield 'fix2' await trio.sleep(0) events.append('fix2 teardown') @@ -220,7 +182,6 @@ def test_after(): 'fix2 teardown', ] """ - ) ) result = testdir.runpytest() @@ -228,28 +189,24 @@ def test_after(): result.assert_outcomes(passed=3) -def test_async_yield_fixture_with_multiple_yields(testdir, async_yield_implementation): +def test_async_yield_fixture_with_multiple_yields(testdir): testdir.makepyfile( - async_yield_implementation( - """ + """ import pytest import trio - from async_generator import async_generator, yield_ @pytest.fixture - @async_generator async def fix1(): await trio.sleep(0) - await yield_('good') + yield 'good' await trio.sleep(0) - await yield_('bad') + yield 'bad' @pytest.mark.trio async def test_actual_test(fix1): pass """ - ) ) result = testdir.runpytest() @@ -259,14 +216,12 @@ async def test_actual_test(fix1): result.assert_outcomes(failed=1) -def test_async_yield_fixture_with_nursery(testdir, async_yield_implementation): +def test_async_yield_fixture_with_nursery(testdir): testdir.makepyfile( - async_yield_implementation( - """ + """ import pytest import trio - from async_generator import async_generator, yield_ async def handle_client(stream): @@ -276,11 +231,10 @@ async def handle_client(stream): @pytest.fixture - @async_generator async def server(): async with trio.open_nursery() as nursery: listeners = await nursery.start(trio.serve_tcp, handle_client, 0) - await yield_(listeners[0]) + yield listeners[0] nursery.cancel_scope.cancel() @@ -291,7 +245,6 @@ async def test_actual_test(server): rep = await stream.receive_some(4) assert rep == b'ping' """ - ) ) result = testdir.runpytest() @@ -299,34 +252,28 @@ async def test_actual_test(server): result.assert_outcomes(passed=1) -def test_async_yield_fixture_crashed_teardown_allow_other_teardowns( - testdir, async_yield_implementation -): +def test_async_yield_fixture_crashed_teardown_allow_other_teardowns(testdir): testdir.makepyfile( - async_yield_implementation( - """ + """ import pytest import trio - from async_generator import async_generator, yield_ setup_events = set() teardown_events = set() @pytest.fixture - @async_generator async def good_fixture(): async with trio.open_nursery() as nursery: setup_events.add('good_fixture setup') - await yield_(None) + yield None teardown_events.add('good_fixture teardown') @pytest.fixture - @async_generator async def bad_fixture(): async with trio.open_nursery() as nursery: setup_events.add('bad_fixture setup') - await yield_(None) + yield None teardown_events.add('bad_fixture teardown') raise RuntimeError('Crash during fixture teardown') @@ -348,7 +295,6 @@ def test_after(): 'good_fixture teardown', } """ - ) ) result = testdir.runpytest() diff --git a/pytest_trio/_tests/test_fixture_mistakes.py b/pytest_trio/_tests/test_fixture_mistakes.py index b00de9f..7bd38ed 100644 --- a/pytest_trio/_tests/test_fixture_mistakes.py +++ b/pytest_trio/_tests/test_fixture_mistakes.py @@ -123,14 +123,12 @@ def test_fixture_cancels_test_but_doesnt_raise(testdir, enable_trio_mode): """ import pytest import trio - from async_generator import async_generator, yield_ @pytest.fixture - @async_generator async def async_fixture(): with trio.CancelScope() as cscope: cscope.cancel() - await yield_() + yield async def test_whatever(async_fixture): @@ -164,4 +162,6 @@ async def test_whatever(mock_clock, extra_clock): result = testdir.runpytest() result.assert_outcomes(failed=1) - result.stdout.fnmatch_lines(["*ValueError: too many clocks spoil the broth!*"]) + result.stdout.fnmatch_lines( + ["*ValueError: Expected at most one Clock in kwargs, got *"] + ) diff --git a/pytest_trio/_tests/test_fixture_ordering.py b/pytest_trio/_tests/test_fixture_ordering.py index c892cd8..a180958 100644 --- a/pytest_trio/_tests/test_fixture_ordering.py +++ b/pytest_trio/_tests/test_fixture_ordering.py @@ -11,7 +11,6 @@ def test_fixture_basic_ordering(testdir): import pytest from pytest_trio import trio_fixture from trio.testing import Sequencer - from async_generator import async_generator, yield_ setup_events = [] teardown_events = [] @@ -21,10 +20,9 @@ def seq(): return Sequencer() @pytest.fixture - @async_generator async def leaf_fix(): setup_events.append("leaf_fix setup") - await yield_() + yield teardown_events.append("leaf_fix teardown") assert teardown_events == [ @@ -36,26 +34,24 @@ async def leaf_fix(): ] @pytest.fixture - @async_generator async def fix_concurrent_1(leaf_fix, seq): async with seq(0): setup_events.append("fix_concurrent_1 setup 1") async with seq(2): setup_events.append("fix_concurrent_1 setup 2") - await yield_() + yield async with seq(4): teardown_events.append("fix_concurrent_1 teardown 1") async with seq(6): teardown_events.append("fix_concurrent_1 teardown 2") @pytest.fixture - @async_generator async def fix_concurrent_2(leaf_fix, seq): async with seq(1): setup_events.append("fix_concurrent_2 setup 1") async with seq(3): setup_events.append("fix_concurrent_2 setup 2") - await yield_() + yield async with seq(5): teardown_events.append("fix_concurrent_2 teardown 1") async with seq(7): @@ -148,7 +144,6 @@ def test_error_collection(testdir): import pytest from pytest_trio import trio_fixture import trio - from async_generator import async_generator, yield_ test_started = False @@ -159,17 +154,15 @@ async def crash_nongen(): raise RuntimeError("crash_nongen".upper()) @trio_fixture - @async_generator async def crash_early_agen(): with trio.CancelScope(shield=True): await trio.sleep(2) raise RuntimeError("crash_early_agen".upper()) - await yield_() + yield @trio_fixture - @async_generator async def crash_late_agen(): - await yield_() + yield raise RuntimeError("crash_late_agen".upper()) async def crash(when, token): @@ -223,12 +216,11 @@ def crashyfix(nursery): crashyfix_using_manual_nursery = """ @trio_fixture - @async_generator async def crashyfix(): async with trio.open_nursery() as nursery: nursery.start_soon(crashy) with pytest.raises(trio.Cancelled): - await yield_() + yield # We should be cancelled here teardown_deadlines["crashyfix"] = trio.current_effective_deadline() """ @@ -243,7 +235,6 @@ async def crashyfix(): import pytest from pytest_trio import trio_fixture import trio - from async_generator import async_generator, yield_ teardown_deadlines = {} final_time = None @@ -300,27 +291,25 @@ def test_complex_cancel_interaction_regression(testdir): """ import pytest import trio - from async_generator import asynccontextmanager, async_generator, yield_ + from contextlib import asynccontextmanager async def die_soon(): raise RuntimeError('oops'.upper()) @asynccontextmanager - @async_generator async def async_finalizer(): try: - await yield_() + yield finally: await trio.sleep(0) @pytest.fixture - @async_generator async def fixture(nursery): async with trio.open_nursery() as nursery1: async with async_finalizer(): async with trio.open_nursery() as nursery2: nursery2.start_soon(die_soon) - await yield_() + yield nursery1.cancel_scope.cancel() @pytest.mark.trio diff --git a/pytest_trio/plugin.py b/pytest_trio/plugin.py index bcb6528..34e64a8 100644 --- a/pytest_trio/plugin.py +++ b/pytest_trio/plugin.py @@ -1,22 +1,15 @@ """pytest-trio implementation.""" from functools import wraps, partial -import sys from traceback import format_exception from collections.abc import Coroutine, Generator -from inspect import iscoroutinefunction, isgeneratorfunction +from contextlib import asynccontextmanager +from inspect import isasyncgen, isasyncgenfunction, iscoroutinefunction import contextvars import outcome import pytest import trio from trio.abc import Clock, Instrument from trio.testing import MockClock -from async_generator import ( - async_generator, - yield_, - asynccontextmanager, - isasyncgen, - isasyncgenfunction, -) ################################################################ # Basic setup @@ -197,13 +190,12 @@ def register_and_collect_dependencies(self): return deps @asynccontextmanager - @async_generator async def _fixture_manager(self, test_ctx): __tracebackhide__ = True try: async with trio.open_nursery() as nursery_fixture: try: - await yield_(nursery_fixture) + yield nursery_fixture finally: nursery_fixture.cancel_scope.cancel() except BaseException as exc: diff --git a/setup.py b/setup.py index 7d1f956..ecf6f8b 100644 --- a/setup.py +++ b/setup.py @@ -17,7 +17,6 @@ entry_points={"pytest11": ["trio = pytest_trio.plugin"]}, install_requires=[ "trio >= 0.22.0", # for ExceptionGroup support - "async_generator >= 1.9", "outcome >= 1.1.0", "pytest >= 7.2.0", # for ExceptionGroup support ], From ce850d6070a345dcef232aae815b4aa067e25e0a Mon Sep 17 00:00:00 2001 From: Zac Hatfield-Dodds Date: Sun, 30 Oct 2022 01:11:24 -0700 Subject: [PATCH 7/8] Create 129.misc.rst --- newsfragments/129.misc.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 newsfragments/129.misc.rst diff --git a/newsfragments/129.misc.rst b/newsfragments/129.misc.rst new file mode 100644 index 0000000..13b403f --- /dev/null +++ b/newsfragments/129.misc.rst @@ -0,0 +1,2 @@ +Dropped support for end-of-life Python 3.6, and the ``async_generator`` library +necessary to support it, and started testing on Python 3.10 and 3.11. From f788fe7d1bc7e7cbfa8e86d482018afd785536d1 Mon Sep 17 00:00:00 2001 From: Zac Hatfield-Dodds Date: Sun, 30 Oct 2022 01:11:24 -0700 Subject: [PATCH 8/8] TEMP: ignore warnings --- pytest.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pytest.ini b/pytest.ini index 54951e1..92c555f 100644 --- a/pytest.ini +++ b/pytest.ini @@ -1,2 +1,2 @@ -[pytest] -addopts = -W error -ra -v --pyargs pytest_trio --verbose --cov +[pytest] +addopts = -ra -v --pyargs pytest_trio --verbose --cov