Closed
Description
I'm working on python/pytest/asyncio since beginning of this year, and when updating pytest-asyncio (from 0.10.0 to 0.12.0) then some previous working tests started to fail.
I have created following minimal example (isolated from a more complex solution) that always fails at teardown.
Can you please let me know if you can reproduce it, and your kind feedback about this potential issue.
Don´t hesitate to ask for any additional information or test on my side.
BR
Angel Luis
Additional info
Versions used to reproduce are:
- pytest-asyncio 0.12.0. (it fails also with 0.11.0)
- pytest 5.4.2
- python 3.8.2
- setuptools 46.2.0 & pip 20.1
- windows 10 Pro [Versión 10.0.18362.175]
Note: Minimal Example works with pytest-asyncio 0.10.0.
Minimal example is the following
import asyncio
import contextlib
import functools
import pytest
@pytest.mark.asyncio
async def test_simple(port):
assert True
@pytest.fixture(scope="module")
def event_loop():
"""Change event_loop fixture to module level."""
loop = asyncio.get_event_loop_policy().new_event_loop()
yield loop
loop.close()
@pytest.fixture(scope="module")
async def port(request, event_loop):
def port_finalizer(finalizer):
async def port_afinalizer():
await finalizer(None, None, None)
event_loop.run_until_complete(port_afinalizer())
context_manager = port_map()
port = await context_manager.__aenter__()
request.addfinalizer(functools.partial(port_finalizer, context_manager.__aexit__))
return port
@contextlib.asynccontextmanager
async def port_map():
worker = asyncio.create_task(background_worker())
yield
try:
worker.cancel()
await worker
except asyncio.CancelledError:
pass
async def background_worker():
while True:
await asyncio.sleep(10.0)
When I run the test I get the following console output:
(venv) C:\git\ATB2\ejemplo_issue>pytest
=================== test session starts =============================
platform win32 -- Python 3.8.2, pytest-5.4.2, py-1.8.1, pluggy-0.13.1
rootdir: C:\git\ATB2\ejemplo_issue
plugins: asyncio-0.12.0
collected 1 item
test_example.py .E [100%]
====================== ERRORS =======================================
______________ ERROR at teardown of test_simple _____________________
finalizer = <bound method _AsyncGeneratorContextManager.__aexit__ of <contextlib._AsyncGeneratorContextManager object at 0x0423AC40>>
def port_finalizer(finalizer):
async def port_afinalizer():
await finalizer(None, None, None)
> event_loop.run_until_complete(port_afinalizer())
test_example.py:24:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
C:\Users\ablasco\AppData\Local\Programs\Python\Python38-32\lib\asyncio\base_events.py:616: in run_until_complete
return future.result()
test_example.py:23: in port_afinalizer
await finalizer(None, None, None)
C:\Users\ablasco\AppData\Local\Programs\Python\Python38-32\lib\contextlib.py:178: in __aexit__
await self.gen.__anext__()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
@contextlib.asynccontextmanager
async def port_map():
worker = asyncio.create_task(background_worker())
yield
try:
worker.cancel()
> await worker
E RuntimeError: Task <Task pending name='Task-4' coro=<port.<locals>.port_finalizer.<locals>.port_afinalizer() running at C:\git\ATB2\ejemplo_issue\test_example.py:23> cb=[_run_until_complete_cb() at C:\Users\ablasco\AppData\Local\Programs\Python\Python38-32
\lib\asyncio\base_events.py:184]> got Future <Task pending name='Task-2' coro=<background_worker() running at C:\git\ATB2\ejemplo_issue\test_example.py:43> wait_for=<Future cancelled>> attached to a different loop
test_example.py:37: RuntimeError
============================= short test summary info ==============================
ERROR test_example.py::test_simple - RuntimeError: Task <Task pending name='Task-4' coro=<port.<locals>.port_finalizer.<locals>.port_afinalizer() running at C:\git\ATB2\ejemplo_issue\test_example.py:23> cb=[_run_until_complete_cb() at C:\Users\ablasco\AppData\Local...
=========================== 1 passed, 1 error in 0.13s =============================
Unexpectedly either of the following changes, made the test to pass:
a) Change fixture to a lower level scope (class or function):
@pytest.fixture(scope="class")
def event_loop():
@pytest.fixture(scope="class")
async def port(request, event_loop):
b) Embed the test inside a class:
class TestClass:
@pytest.mark.asyncio
async def test_simple(port):
assert True
c) Or change finalizer to call get_event_loop (instead of using event_loop from fixture)
def port_finalizer(finalizer):
async def port_afinalizer():
await finalizer(None, None, None)
# event_loop.run_until_complete(port_afinalizer())
loop = asyncio.get_event_loop()
loop.run_until_complete(port_afinalizer())
Metadata
Metadata
Assignees
Labels
No labels