-
Notifications
You must be signed in to change notification settings - Fork 4
Description
Feature request
In the context of migrating away from nest_asyncio, I ended up using greenback. In order to support cases where the user 1. executes code (including imports) in a pre-existing asyncio Task (jupyterlab notebook) and 2. with non-stdlib event loops (uvloop when using gunicorn), the least intrusive setup seemed to be creating an internal thread running an event loop that:
- The project has full control on (since it's not exposed directly)
- Has a custom event loop that overrides
create_task()to to wrap all coroutines with:
def _wrap_coro(coro):
async def coro_f():
await greenback.ensure_portal()
return await coro
return coro_f()This way it can achieve a result similar to with_portal_run_tree() on asyncio, as all Tasks created by this event loop will be portaled appropriately.
If a turnkey high-level solution is in the scope of greenback, this makes it possible to provide an implementation of asyncio.run() that is re-entrant, achieving the same result as nest_asyncio (with an extra thread, but working for any asyncio event loop rather than just the stdlib implementations).
An implementation (including the re-entrant run() function) is available here: https://github.com/ARM-software/devlib/pull/683/files
Note: wrapping an event loop into another class requires some __getattribute__ tricks, as asyncio.AbstractEventLoop provides a default implementation of all (?) methods that just raise. This makes it impossible to use __getattr__ to delegate non-overridden calls to the wrapped loop, see our _GreenbackEventLoop implementation.