unasync icon indicating copy to clipboard operation
unasync copied to clipboard

JIT

Open davidbrochart opened this issue 3 years ago • 3 comments

Would it make sense to allow for just-in-time generation (and execution) of the synchronous code?

davidbrochart avatar Mar 09 '21 16:03 davidbrochart

You'd run into problems where the code is used within a read-only file system. There would also be problems with type hints/suggestions when developing with the code.

sethmlarson avatar Mar 09 '21 20:03 sethmlarson

Right, JIT seems like too much magic. Why would you need that?

Reading https://github.com/jupyter/jupyter_client/issues/624, what seems more useful is to be able to tell unasync to ignore code that is deliberately async. Another option is to call async code from the sync parts, possibly using the world's simplest coroutine runner:

def _run_secretly_sync_async_fn(async_fn, *args, **kwargs):
    coro = async_fn(*args, **kwargs)
    try:
        coro.send(None)
    except StopIteration as exc:
        return exc.value
    else:
        raise RuntimeError("this async function is not secretly synchronous")

(Even though that won't help for _async_poll_for_reply in nbclient.)

For what it's worth, unasync is currently used successfully in httpcore and the Python Elasticsearch client. As as unasync maintainer, I'm very interested to see use cases where it does not work, so I subscribed to that issue and will be interested to see what comes out of it.

pquentin avatar Mar 10 '21 05:03 pquentin

Right, JIT seems like too much magic. Why would you need that?

Essentially to not worry about the generated sync files: whether to commit them or not, having the extra step of generating them each time the async code changes... Generating sync code on the fly would feel much more like there is one source of truth.

Reading jupyter/jupyter_client#624, what seems more useful is to be able to tell unasync to ignore code that is deliberately async.

But then in the sync world you'll have to run this code until complete in an event loop, which is what we wanted to avoid with unasync.

Another option is to call async code from the sync parts, possibly using the world's simplest coroutine runner:

def _run_secretly_sync_async_fn(async_fn, *args, **kwargs):
    coro = async_fn(*args, **kwargs)
    try:
        coro.send(None)
    except StopIteration as exc:
        return exc.value
    else:
        raise RuntimeError("this async function is not secretly synchronous")

(Even though that won't help for _async_poll_for_reply in nbclient.)

I don't see how you can run async code with this function, but yes running a coroutine until complete in an event loop is an option, although it also comes with complications when an event loop is already running.

For what it's worth, unasync is currently used successfully in httpcore and the Python Elasticsearch client. As as unasync maintainer, I'm very interested to see use cases where it does not work, so I subscribed to that issue and will be interested to see what comes out of it.

Good to know, for jupyter-client I came to the conclusion that unasync is not an option, as we (can) have async code that is impossible to translate to sync.

davidbrochart avatar Mar 10 '21 08:03 davidbrochart