Is it possible to make a decorator working with asynchronous and synchronous functions?

Let's say there is simply a decorator:
def if_no_data(f):
 def wrapper(self, *args, **kwargs):
 if not self.data:
 return f(self, *args, **kwargs)

 return wrapper

The essence of his work is simple - check for the emptiness of the object property. Great, but if it is necessary that the decorator has worked with both the asynchronous and synchronous functions?
Something looks very strange, and hardly will work.
def if_no_data(f):
 async def wrapper(self, *args, **kwargs):
 if not self.data:
 result = f(self, *args, **kwargs)

try:
 return await result
 except ValueError:
 return result

 return wrapper
March 19th 20 at 09:12
1 answer
March 19th 20 at 09:14
Solution
Something like that

def if_no_data(f):
 async def wrapper(self, *args, **kwargs):
 if self.data:
 return None

 if asyncio.iscoroutinefunction(f):
 return await f(self, *args, **kwargs)
else:
 return f(self, *args, **kwargs)

 return wrapper
And, about iscoroutinefunction didn't thought how to Dodge. But then the second question arises -- how to call the decorated function?

for example:
@if_no_data
def a(): pass

@if_no_data
async def b(): pass

always will be
await a()
await b()

? - maia commented on March 19th 20 at 09:17
@maia, yeah, because the wrapper in the decorator - coroutine - Colton commented on March 19th 20 at 09:20

Find more questions by tags Asynchronous programmingPython