You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In this way, I can call the async asum function with await asum(1, 2), but if I check whether asum is a coroutine function with inspect.iscoroutinefunction, it returns False.
But this time, calling inspect.iscoroutinefunction(sum) and inspect.iscoroutinefunction(asum) will both return True.
Is there any way I can write a custom decorator that supports both sync and async function with decorator package? If not, would you consider supporting this use case?
The text was updated successfully, but these errors were encountered:
Of course you could wrap decorator if you don't want to do this manually for every decorated async function.
Background
Python allows creating callables which are not coroutines (not defined with async) but still return awaitables (work with await).
So everyone who uses inspect.iscoroutinefunction to decide whether to use await is technically wrong (but Python itself has at least half the blame here - the need for something like inspect.markcoroutinefunction has been blatantly obvious for at least five years now, and arguably should've been obvious when first designing the async/await language addition back in 3.5).
inspect.iscoroutinefunction is a half check. If it returns True we know we should use await, but if it returns Falsewe haven't actually disproven if we should use await.
So instead of
ifinspect.iscoroutinefunction(f):
result=awaitf(...) # correctelse:
result=f(...) # could be wrong, f might return an awaitable
And if we're in a wrapper that needs to support both sync and async functions, you just return whatever f returned, which makes you transparent w.r.t. to whether an await is needed on your return value:
returnf(...)
I infer decorator is using that last method, which is technically the most correct thing to do, but sadly it just pushes this obscure edge-case further up the call-stack, making it everyone else's problem.
So decorator could be written to progressively enhance: try importing inspect.markcoroutinefunction - if it's not available just don't use it, but if it is, check the wrapped callable with inspect.iscoroutinefunction and mark the wrapper to match.
In Python without
decorator
package, if I want to create a custom decorator that supports both sync and async function, I can write the following:However, with the
decorator
package, how can I write a custom decorator that supports both sync and async function?I've tried this way: (minimal example)
In this way, I can call the async
asum
function withawait asum(1, 2)
, but if I check whetherasum
is a coroutine function withinspect.iscoroutinefunction
, it returnsFalse
.I've also tried another way:
But this time, calling
inspect.iscoroutinefunction(sum)
andinspect.iscoroutinefunction(asum)
will both returnTrue
.Is there any way I can write a custom decorator that supports both sync and async function with
decorator
package? If not, would you consider supporting this use case?The text was updated successfully, but these errors were encountered: