I'm looking to create a function that is callable by both synchronous and asynchronous code. When called under the context of a running coroutine, it would return an awaitable object otherwise it would simply return the result.
Also I'm looking for a more general result that applies to using coroutines in all python not just asyncio.
import inspect
class awaitable:
def __await__(self):
return (yield 42)
def is_coroutine_running():
#print(inspect.getouterframes(inspect.currentframe()))
# ???
return True
def awaitable_when_called_by_coroutine():
if is_coroutine_running():
return awaitable()
else:
return 42
def sync_call():
print("sync_call", awaitable_when_called_by_coroutine())
async def async_call():
print("async_call", await awaitable_when_called_by_coroutine())
if __name__ == "__main__":
sync_call()
coro = async_call()
assert(coro.send(None) == 42)
try:
coro.send(42)
except StopIteration:
pass
CURRENT OUTPUT
sync_call <__main__.awaitable object at 0x000002E0FE5347F0>
async_call 42
EXPECTED OUTPUT
sync_call 42
async_call 42
IDEAS
Search up the callstack to find a code object with inspect.CO_COROUTINE set
https://docs.python.org/3/library/inspect.html?highlight=inspect#inspect.CO_COROUTINE
See if CPython holds any state on the currently running coroutine.