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
```