Description
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:
import inspect
def custom_decorator(func):
if inspect.iscoroutinefunction(func):
# Support for async functions
async def awrapper(*args, **kwargs):
print("custom_decorator")
return await func(*args, **kwargs)
return awrapper
else:
# Support for sync functions
def wrapper(*args, **kwargs):
print("custom_decorator")
return func(*args, **kwargs)
return wrapper
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)
from decorator import decorator
import asyncio
@decorator
def custom_decorator(func, *args, **kwargs):
print("custom_decorator_start")
return func(*args, **kwargs)
@custom_decorator
def sum(x, y):
return x+y
@custom_decorator
async def asum(x, y):
await asyncio.sleep(1)
return x+y
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
.
I've also tried another way:
import inspect
from decorator import decorator
import asyncio
@decorator
async def custom_decorator(func, *args, **kwargs):
print("custom_decorator_start")
if inspect.iscoroutinefunction(func):
return await func(*args, **kwargs)
else:
return func(*args, **kwargs)
@custom_decorator
def sum(x, y):
return x+y
@custom_decorator
async def asum(x, y):
await asyncio.sleep(1)
return x+y
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?