pytest-dev/pytest-asyncio

Cannot create subprocess when using `forbid_global_loop`

AndreLouisCaron opened this issue · 1 comments

I just added the forbid_global_loop parameter to the asyncio marker. Most tests pass fine, I fixed a few others with accidental references to the default event loop. However, some of them fail in a strange way:

asyncio/base_events.py:342: in run_until_complete
    return future.result()
asyncio/futures.py:274: in result
    raise self._exception
asyncio/tasks.py:239: in _step
    result = coro.send(value)
gitmesh/storage.py:35: in check_output
    loop=loop,
asyncio/subprocess.py:197: in create_subprocess_shell
    stderr=stderr, **kwds)
asyncio/base_events.py:940: in subprocess_shell
    protocol, cmd, True, stdin, stdout, stderr, bufsize, **kwargs)
asyncio/unix_events.py:179: in _make_subprocess_transport
    with events.get_child_watcher() as watcher:
asyncio/events.py:604: in get_child_watcher
    return get_event_loop_policy().get_child_watcher()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <pytest_asyncio.plugin.ForbiddenEventLoopPolicy object at 0x103dbba20>

    def get_child_watcher(self):
        "Get the watcher for child processes."
>       raise NotImplementedError
E       NotImplementedError

Seems like, at least on OSX, the asyncio subprocess facilities depend on an undocumented get_child_watcher() method of the event loop policy.

I'm guessing part of this problem exceeds the scope of this project: custom event loops must conform to an undocumented interface to be able to support subprocesses. I'm guessing this needs to be discussed with asyncio maintainers.

However, I guess you'll also want to do something about this in this library because pytest_asyncio.plugin.ForbiddenEventLoopPolicy currently doesn't implement this hidden interface.

Interesting!

I guess the main question here is, why is asyncio not using the event loop itself, but reaching for the event_loop policy? The policy could be something completely unrelated to the loop currently running.

Maybe I'll go ask on the asyncio mailing list about this.