The idea on the OP can be fully implemented with ~10 lines of code in a
decorator -
which could be further factored out into a decorator-for-decorators:
```
import asyncio, inspect
def hybrid_decorator(func):
coro = inspect.iscoroutinefunction(func)
if coro:
async def inner(*args, **kw):
return await func(*args, **kw)
else:
def inner(*args, **kw):
return func(*args, **kw)
def wrapper(*args, **kw):
...
value = inner(*args, **kw)
...
return value
if coro:
wrapper = asyncio.coroutine(wrapper)
return wrapper
```
The thing is that just in Python 3.8 the `@courotine` decorator has been
deprecated -
not sure if there is another "in language" way of changing an already
defined,
no "await" in body, function to a coroutine function.
One way or another, this approach seems quite feasible for whoever wants
to make use of such a feature with no need for new syntax (but maybe need
for having an "undeprecated" way of doing what `@coroutine` does)
Here is the approach factored out to a "decorator decorator" that does the
dirty job:
```
def hybrid_async(deco):
@wraps(deco)
def wrapper(func):
coro = inspect.iscoroutinefunction(func)
if coro:
async def inner(*args, **kw):
return await func(*args, **kw)
else:
inner = func
wrapped = wraps(func)(deco(inner))
if coro:
wrapped = asyncio.coroutine(wrapped)
return wrapped
return wrapper
@hybrid_async
def log_run(func):
@wraps(func)
def wrapper(*args, **kw):
print("start", flush=True)
v = func(*args, **kw)
print("stop", flush=True)
return v
return wrapper
```
On Tue, 11 Feb 2020 at 11:59, Soni L.
On Mon, Feb 10, 2020 at 9:50 AM Andrew Barnert via Python-ideas
wrote: It’s a well-known problem that async is “contagious”: [...]
But C# and every other language that’s borrowed the idea has the same
On 2020-02-11 4:33 a.m., Ben Rudiak-Gould wrote: problem, and as far as I know, nobody’s thought of a good answer yet.
Threads don't have that problem: you can use non-thread-aware code with callbacks in your threaded program if you do your own locking. Haskell (GHC) doesn't have that problem: it has fibers that use a programming interface like C#/Python threads, but they're multiplexed by user-mode code within a single OS thread. 16-bit Windows didn't have that problem. Stackless and greenlet don't have that problem.
It's a problem that can be solved by just doing the obvious thing, the thing that Python already did with threads: don't define a novel syntax for coroutines, but instead use the syntax that already existed.
Async/await syntax is a static type system with two types, may-yield and will-not-yield. There's no provision for writing generic/polymorphic code over those types, so you have to write everything twice. Like any static type system it has some benefits, but I don't think it's worth the cost, especially in Python, which has always eschewed mandatory static typing.
I don't know how to fix Python now that it's gone so thoroughly down this path (starting with the yield keyword 18 years ago). But it's not a problem that ever needed to exist. Coroutines aren't that hard.
I would suggest having an "await in" operator. Or an "autowait" function:
def autowait(value): if is_awaitable(value): return value async def force_await(): return value return force_await()
This would allow one to write "async-ready" code while calling non-async functions.
-- Ben _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/ZDQIZ5... Code of Conduct: http://python.org/psf/codeofconduct/
Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/P4SHOV... Code of Conduct: http://python.org/psf/codeofconduct/