tools (utils): Add maybe_async function:
`maybe_async` can be used to call a function which may be or not `async`. It doesn't use `defer.ensureDeferred` contrary to `ad_defered`, so the call stack is not lost, and it's easier to debug when an Exception is raised.
This commit is contained in:
parent
bf93abb343
commit
286e931a7f
1 changed files with 25 additions and 4 deletions
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
"""various useful methods"""
|
||||
|
||||
from typing import Optional, Union
|
||||
from typing import Any, Optional, Union
|
||||
import unicodedata
|
||||
import os.path
|
||||
import datetime
|
||||
|
|
@ -92,12 +92,13 @@ def partial(func, *fixed_args, **fixed_kwargs):
|
|||
|
||||
return method
|
||||
|
||||
|
||||
def as_deferred(func, *args, **kwargs):
|
||||
def as_deferred(func, *args, **kwargs) -> defer.Deferred:
|
||||
"""Call a method and return a Deferred
|
||||
|
||||
the method can be a simple callable, a Deferred or a coroutine.
|
||||
It is similar to defer.maybeDeferred, but also handles coroutines
|
||||
It is similar to defer.maybeDeferred, but also handles coroutines.
|
||||
Due to the use of ``defer.ensureDeferred``, the call stack may be lost, which can make
|
||||
debugging harder in case of Exception, the function ``maybe_async`` below solves this.
|
||||
"""
|
||||
try:
|
||||
ret = func(*args, **kwargs)
|
||||
|
|
@ -114,6 +115,26 @@ def as_deferred(func, *args, **kwargs):
|
|||
return defer.succeed(ret)
|
||||
|
||||
|
||||
async def maybe_async(ret: Any) -> Any:
|
||||
"""Check if a return value is awaitable and await it if necessary.
|
||||
|
||||
This function checks whether the return value of a method is awaitable. If it is, the
|
||||
function awaits on it and returns the awaited value. Otherwise, it returns the value
|
||||
as-is.
|
||||
|
||||
Unlike ``as_deferred``, this function does not call ``defer.ensureDeferred``, so it
|
||||
must be used within an already ``async`` context where ``defer.ensureDeferred`` has
|
||||
already been called at a higher level. This makes debugging easier by preserving the
|
||||
call stack in case of exceptions.
|
||||
|
||||
@param ret: The return value of a function, which may be awaitable or not.
|
||||
@return: The awaited value if the input was awaitable, otherwise the input as-is.
|
||||
"""
|
||||
if inspect.isawaitable(ret):
|
||||
return await ret
|
||||
return ret
|
||||
|
||||
|
||||
def aio(func):
|
||||
"""Decorator to return a Deferred from asyncio coroutine
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue