Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

KeyboardInterrupt during async generator fixture setup results in RuntimeError #219

Closed
kriek opened this issue Jul 9, 2021 · 2 comments · Fixed by #221
Closed

KeyboardInterrupt during async generator fixture setup results in RuntimeError #219

kriek opened this issue Jul 9, 2021 · 2 comments · Fixed by #221

Comments

@kriek
Copy link
Contributor

kriek commented Jul 9, 2021

Hello there,

I'm using asyncio-0.15.1 and it seems there is a bug when pytest is interrupted during the setup code of an async generator fixture.

Minimal reproduction test module:

import pytest
import asyncio

@pytest.fixture
async def fixture():
	await asyncio.sleep(5)
	yield
	await asyncio.sleep(1)

@pytest.mark.asyncio
async def test_keyboard_interrupt(fixture):
	pass

If I hit Ctrl-C during fixture setup, it results in:

D:\python>pytest test_keyboard_interrupt.py
============================================================================================ test session starts ============================================================================================
platform win32 -- Python 3.8.5, pytest-6.1.2, py-1.9.0, pluggy-0.13.1
rootdir: D:\python
plugins: asyncio-0.15.1
collected 1 item

test_keyboard_interrupt.py
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! KeyboardInterrupt !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
c:\users\kasyc\appdata\local\programs\python\python38\lib\asyncio\windows_events.py:779: KeyboardInterrupt
(to show a full traceback on KeyboardInterrupt use --full-trace)
Traceback (most recent call last):
  File "c:\users\kasyc\appdata\local\programs\python\python38\lib\runpy.py", line 194, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "c:\users\kasyc\appdata\local\programs\python\python38\lib\runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "C:\Users\kasyc\AppData\Local\Programs\Python\Python38\Scripts\pytest.exe\__main__.py", line 7, in <module>
  File "c:\users\kasyc\appdata\local\programs\python\python38\lib\site-packages\_pytest\config\__init__.py", line 187, in console_main
    code = main()
  File "c:\users\kasyc\appdata\local\programs\python\python38\lib\site-packages\_pytest\config\__init__.py", line 164, in main
    ret = config.hook.pytest_cmdline_main(
  File "c:\users\kasyc\appdata\local\programs\python\python38\lib\site-packages\pluggy\hooks.py", line 286, in __call__
    return self._hookexec(self, self.get_hookimpls(), kwargs)
  File "c:\users\kasyc\appdata\local\programs\python\python38\lib\site-packages\pluggy\manager.py", line 93, in _hookexec
    return self._inner_hookexec(hook, methods, kwargs)
  File "c:\users\kasyc\appdata\local\programs\python\python38\lib\site-packages\pluggy\manager.py", line 84, in <lambda>
    self._inner_hookexec = lambda hook, methods, kwargs: hook.multicall(
  File "c:\users\kasyc\appdata\local\programs\python\python38\lib\site-packages\pluggy\callers.py", line 208, in _multicall
    return outcome.get_result()
  File "c:\users\kasyc\appdata\local\programs\python\python38\lib\site-packages\pluggy\callers.py", line 80, in get_result
    raise ex[1].with_traceback(ex[2])
  File "c:\users\kasyc\appdata\local\programs\python\python38\lib\site-packages\pluggy\callers.py", line 187, in _multicall
    res = hook_impl.function(*args)
  File "c:\users\kasyc\appdata\local\programs\python\python38\lib\site-packages\_pytest\main.py", line 306, in pytest_cmdline_main
    return wrap_session(config, _main)
  File "c:\users\kasyc\appdata\local\programs\python\python38\lib\site-packages\_pytest\main.py", line 294, in wrap_session
    config.hook.pytest_sessionfinish(
  File "c:\users\kasyc\appdata\local\programs\python\python38\lib\site-packages\pluggy\hooks.py", line 286, in __call__
    return self._hookexec(self, self.get_hookimpls(), kwargs)
  File "c:\users\kasyc\appdata\local\programs\python\python38\lib\site-packages\pluggy\manager.py", line 93, in _hookexec
    return self._inner_hookexec(hook, methods, kwargs)
  File "c:\users\kasyc\appdata\local\programs\python\python38\lib\site-packages\pluggy\manager.py", line 84, in <lambda>
    self._inner_hookexec = lambda hook, methods, kwargs: hook.multicall(
  File "c:\users\kasyc\appdata\local\programs\python\python38\lib\site-packages\pluggy\callers.py", line 203, in _multicall
    gen.send(outcome)
  File "c:\users\kasyc\appdata\local\programs\python\python38\lib\site-packages\_pytest\terminal.py", line 794, in pytest_sessionfinish
    outcome.get_result()
  File "c:\users\kasyc\appdata\local\programs\python\python38\lib\site-packages\pluggy\callers.py", line 80, in get_result
    raise ex[1].with_traceback(ex[2])
  File "c:\users\kasyc\appdata\local\programs\python\python38\lib\site-packages\pluggy\callers.py", line 187, in _multicall
    res = hook_impl.function(*args)
  File "c:\users\kasyc\appdata\local\programs\python\python38\lib\site-packages\_pytest\runner.py", line 104, in pytest_sessionfinish
    session._setupstate.teardown_all()
  File "c:\users\kasyc\appdata\local\programs\python\python38\lib\site-packages\_pytest\runner.py", line 411, in teardown_all
    self._pop_and_teardown()
  File "c:\users\kasyc\appdata\local\programs\python\python38\lib\site-packages\_pytest\runner.py", line 386, in _pop_and_teardown
    self._teardown_with_finalization(colitem)
  File "c:\users\kasyc\appdata\local\programs\python\python38\lib\site-packages\_pytest\runner.py", line 404, in _teardown_with_finalization
    self._callfinalizers(colitem)
  File "c:\users\kasyc\appdata\local\programs\python\python38\lib\site-packages\_pytest\runner.py", line 401, in _callfinalizers
    raise exc
  File "c:\users\kasyc\appdata\local\programs\python\python38\lib\site-packages\_pytest\runner.py", line 394, in _callfinalizers
    fin()
  File "c:\users\kasyc\appdata\local\programs\python\python38\lib\site-packages\_pytest\fixtures.py", line 1032, in finish
    raise exc
  File "c:\users\kasyc\appdata\local\programs\python\python38\lib\site-packages\_pytest\fixtures.py", line 1025, in finish
    func()
  File "c:\users\kasyc\appdata\local\programs\python\python38\lib\site-packages\pytest_asyncio\plugin.py", line 139, in finalizer
    loop.run_until_complete(async_finalizer())
  File "c:\users\kasyc\appdata\local\programs\python\python38\lib\asyncio\base_events.py", line 616, in run_until_complete
    return future.result()
  File "c:\users\kasyc\appdata\local\programs\python\python38\lib\site-packages\pytest_asyncio\plugin.py", line 131, in async_finalizer
    await gen_obj.__anext__()
RuntimeError: anext(): asynchronous generator is already running

It seems we would need to transform:

            request.addfinalizer(finalizer)
            return loop.run_until_complete(setup())

into:

            result = loop.run_until_complete(setup())
            request.addfinalizer(finalizer)
            return result

so that the cleanup code will only be executed if the setup code is finished.

@kriek
Copy link
Contributor Author

kriek commented Jul 16, 2021

I created #221 PR but I don't know how to link it to this issue.

@kriek
Copy link
Contributor Author

kriek commented Oct 18, 2021

Can we have the PR merged and if possible shipped in a release?

asvetlov added a commit that referenced this issue Jan 11, 2022
Co-authored-by: Andrew Svetlov <andrew.svetlov@gmail.com>
clrpackages pushed a commit to clearlinux-pkgs/pypi-pytest_asyncio that referenced this issue Jan 17, 2022
… to version 0.17.0

Andrew Svetlov (20):
      Add 'Framework :: Asyncio' trove classifier
      Reformat with black
      Fix readme, the plugin now provide fixtures for unused udp ports also (#241)
      Ignote .python-version file marker
      Update changelog for added plugin modes (#243)
      Avoid non-stantdard approached for warning emitting (#242)
      Rewrite flaky integration test (#246)
      Setup pre-commit hooks and reformat code (#245)
      Setup initial codeowners (#244)
      Switch to declarative setup (#247)
      Fix typo
      Configure dependabot version updater (#250)
      Setup GitHub Workflows linter and yaml-reformatter (#253)
      Release process automation (#252)
      Build on tag
      Fix trove classifier for asyncio
      Fix release artifacts
      Convert README.rst to Markdown for making githun release
      Fix pandoc installation procedure
      Bump to 0.17 release

Bruno Oliveira (2):
      Add note about unittest.TestCase not being supported
      Mention IsolatedAsyncioTestCase

Dominik S. Buse (1):
      Add unused port helpers for UDP (#99)

Imran Hayder (1):
      Switch to setuptools-scm for versioning (#37)

Kian-Meng, Ang (1):
      Fix typo

Michael Seifert (7):
      Teardown of the event_loop fixture no longer replaces the event loop policy.
      refactor: Removed use of obsolete transfer_markers during test collection phase.
      feat!: Drop support for Python 3.6.
      refactor: Moved test_hypothesis_integration to "hypothesis" subfolder and renamed it to "test_base".
      fix: Fixed double wrapping of inherited Hypothesis tests.
      doc: Updated docstring of pytest_pyfunc_call.
      doc: Mentioned additional test dependency on flaky in the changelog.

Nikita Sobolev (1):
      Use `python@3.10` in CI

Piper Merriam (1):
      Add mechanism for explicit marking of fixtures which should be run with asyncio (#125)

Tin Tvrtkovic (2):
      Update CI badge
      Durr

dependabot[bot] (1):
      Bump codecov/codecov-action from 1 to 2.1.0 (#251)

kriek (1):
      Fixes pytest-dev/pytest-asyncio#219 (#221)

wjsi (1):
      Support flaky on async tests
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant