Open Tinche opened 2 years ago
What do you get for:
type(coroutine_func())
Am inclined to think this is a shortcoming in Python implementation of coroutines in that it doesn't cope well with decorated functions, or certainly not ones where the decorated function is actual using a decorator which is a descriptor.
If you use older asyncio.coroutine
decorator you get:
>>> @asyncio.coroutine
... @dec
... def my_func(): pass
...
>>> my_func().__name__
'my_func'
>>> type(my_func())
<class 'generator'>
Although if switch that around you get:
>>> @dec
... @asyncio.coroutine
... def my_func(): pass
...
>>> my_func().__name__
'dec'
>>> type(my_func())
<class 'coroutine'>
showing wrong name, with result being a different type as well, which is strange.
So right now not really sure. I can't really work out how the async
keyword magic happens.
It might be interesting to do some test with decorator coroutines where decorator uses normal function closure and functools.wraps
. If it works with that probably shows that a decorator implemented as a descriptor is the issue.
Yep, looks like functools.wraps
will do the trick.
from functools import wraps
def dec(fn):
@wraps(fn)
def wrapper(*args, **kwargs):
return fn(*args, **kwargs)
return wrapper
@dec
async def coroutine_func():
pass
print(coroutine_func.__name__) # is 'coroutine_func' as expected
print(coroutine_func().__name__) # is 'coroutine_func' as expected
prints outs:
coroutine_func
coroutine_func
(and a warning that's not relevant)
Should we open up a CPython issue? Could you do it since I think you have a much better grasp of what's going on?
Hello!
I've come up against this while working on an asyncio job library. Maybe it's best if I paste a code example.
Can anything be done about this in wrapt, or is this too lost a case?