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

Use a loop proxy for better flexibility #235

Open
asvetlov opened this issue Jan 3, 2022 · 4 comments
Open

Use a loop proxy for better flexibility #235

asvetlov opened this issue Jan 3, 2022 · 4 comments

Comments

@asvetlov
Copy link
Contributor

asvetlov commented Jan 3, 2022

aioloop-proxy provide a proxy instance that is fully compatible with asyncio.AbstractEventLoop but allows to cooperate of multiple nested proxies at the same time.

From pytest-asyncio point of view, a session-scope fixture can use a session-level loop proxy that can cooperate with module-level, class-level, and function-level ones providing good test isolation.

I have no proof of concept for pytest-asyncio yet, if somebody with deep pytest internals knowledge can help -- you are welcome!

@seifertm
Copy link
Contributor

seifertm commented Jan 5, 2022

This sounds interesting! As you mentioned in another comment the loop proxy could address many things related to loop teardown and orphaned tasks, because the context manager takes care of this when it exits. aioloop-proxy also includes an advance_time method, which has been proposed in #113.

I played around with aioloop-proxy a bit. A large number of tests already work when replacing a couple of lines in wrap_in_sync:

def wrap_in_sync(func, _loop):
…
        if coro is not None:
            try:
                with aioloop_proxy.proxy(_loop) as loop_proxy:
                    task = asyncio.ensure_future(coro, loop=loop_proxy)
                    loop_proxy.run_until_complete(task)
            except BaseException:
…

The failing tests were mostly related to subprocesses or setting a custom event loop or policy. Some special usage like the one in TestEventLoopStartedBeforeFixtures break, because the tasks in the test cases get attached to a different loop.

Anyway, the new information made me wonder if the event_loop fixture still makes sense when using aioloop-proxy.

That's all I got for now :)

@asvetlov
Copy link
Contributor Author

asvetlov commented Jan 6, 2022

From my point of view, the plugin should support two modes.

  1. In compatible mode the event_loop fixture works as-is; it is crucial for the sake of backward compatibility.
  2. The proxy mode has no event_loop but works differently.

An overridable session-scope fixture exists that returns a root loop instance. An user can override this fixture in conftest.py to start a non-standard event loop, e.g. uvloop or qasync. The root fixture maker should be named differently than event_loop to don't clash with compatible mode.

Each pytest node should have a loop proxy instance created from the proxy of the parent loop. node._store (or plugin-level cache if compatibility with older pytest versions is required) can be used to keep proxy loops tree.
I doubt if we need a fixture for getting the active event loop proxy instance since dropping Python 3.6 support. asyncio.get_running_loop() is always available; it follows loop argument removals from asyncio API.

@seifertm
Copy link
Contributor

seifertm commented Jan 16, 2022

Issue #91 is yet another problem that caused by the event_loop fixture not cleaning up existing tasks. It seems like a number of people are affected by this.

@asvetlov @Tinche Would it make sense to clean up open tasks before closing the current loop? This could serve as an intermediate solution until we integrate aioloop-proxy? It's not as nice, but it would be a smaller step in the right direction.

@asvetlov
Copy link
Contributor Author

Good question!
My plan was to make 0.17.1 bugfix release and start integrating aioloop-proxy

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

No branches or pull requests

2 participants