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

Regression in 0.25.2 - Event loop is closed #1040

Closed
schlamar opened this issue Jan 8, 2025 · 7 comments · Fixed by #1051
Closed

Regression in 0.25.2 - Event loop is closed #1040

schlamar opened this issue Jan 8, 2025 · 7 comments · Fixed by #1051
Milestone

Comments

@schlamar
Copy link

schlamar commented Jan 8, 2025

If there is a user defined fixture which handles loop shutdown and closing the loop on its own, the plugin raises an error.

Expected behavior: If user code closes the event loop, pytest-asyncio should handle this transparently.

Actual behavior: pytest-asyncio raises RuntimeError: Event loop is closed.

..\..\AppData\Local\Programs\Python\Python310\lib\contextlib.py:142: in __exit__
    next(self.gen)
.venv\lib\site-packages\pytest_asyncio\plugin.py:1168: in _provide_event_loop
    loop.run_until_complete(loop.shutdown_asyncgens())
..\..\AppData\Local\Programs\Python\Python310\lib\asyncio\base_events.py:624: in run_until_complete
    self._check_closed()

Example working with 0.25.1, crashes with 0.25.2:

import asyncio

import pytest


@pytest.fixture(autouse=True)
def handle_event_loop(request: pytest.FixtureRequest):
    event_loop = None
    if "event_loop" in request.fixturenames:
        event_loop = request.getfixturevalue("event_loop")

    yield

    if event_loop is None or event_loop.is_closed():
        return
    try:
        asyncio.runners._cancel_all_tasks(event_loop)
        event_loop.run_until_complete(event_loop.shutdown_asyncgens())
        if hasattr(event_loop, "shutdown_default_executor"):  # Python 3.9+
            event_loop.run_until_complete(event_loop.shutdown_default_executor())
    finally:
        event_loop.close()


async def test():
    assert True
@seifertm
Copy link
Contributor

Thanks for the detailed report!
A patch release shouldn't introduce a breaking change. We should address this in a new v0.25 release.
It's also quite easy to address in pytest-asyncio.

@bradydean
Copy link

I am also getting this error with my doctests.

@medihack
Copy link

The error occurs already with v0.25.1 (in my case, when using it together with pytest-playwright).

@minrk
Copy link
Contributor

minrk commented Jan 27, 2025

fwiw, another related regression in #1034 is that the shutdown can apparently also fail with CancelledError, which I guess should be suppressed? I'm not sure how/why, but we're seeing that. Might be something weird we are doing, but i think it is in general related to the fact that our own event-loop cleanup code conflicts with pytest-asyncio unconditionally cleaning things up without checking if it can/should.

@schlamar
Copy link
Author

The error occurs already with v0.25.1 (in my case, when using it together with pytest-playwright).

@medihack This has to be another issue. The problem I'm describing here is the direct cause of a change introduced in 0.25.2. Please try to check if your problem is not a user issue or an issue with pytest-playwright.

If you get a reproducible test case working with 0.25.0 but not with 0.25.1 and 0.25.2, please open a separate issue as this is very likely unrelated and probably requires a different bug fix.

@seifertm
Copy link
Contributor

fwiw, another related regression in #1034 is that the shutdown can apparently also fail with CancelledError, which I guess should be suppressed? I'm not sure how/why, but we're seeing that. Might be something weird we are doing, but i think it is in general related to the fact that our own event-loop cleanup code conflicts with pytest-asyncio unconditionally cleaning things up without checking if it can/should.

The asyncio.Runner.close doesn't seem to handle CancelledErrors explicitly, neither in shutdown_asyncgens, nor in _cancel_all_tasks. It does forward any exceptions to the loop's default exception handler, though.

Suppressing these errors seems like a good idea, until #205 is tackled.

@seifertm
Copy link
Contributor

Pytest-asyncio v0.25.3 is available, which should address this issue.

Thanks to @minrk for contributing the bug fix!

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.

5 participants