bpo-34890: Make iscoroutinefunction, isgeneratorfunction and isasyncgenfunction work with functools.partial#9903
Conversation
…work with partial
Lib/inspect.py
Outdated
| object.__code__.co_flags & CO_GENERATOR) | ||
| is_partial_generator = bool((isinstance(object, functools.partial) and | ||
| object.func.__code__.co_flags & CO_GENERATOR)) | ||
| return is_generator_function or is_partial_generator |
There was a problem hiding this comment.
Wouldn't it be better to do this:
while isinstance(object, functools.partial):
object = object.func? The benefit would be support of nested partials and the code will probably look less ugly.
There was a problem hiding this comment.
Also, while you're here, please rename object to obj or o.
Lib/inspect.py
Outdated
| """ | ||
| return bool((isfunction(object) or ismethod(object)) and | ||
| object.__code__.co_flags & CO_ASYNC_GENERATOR) | ||
| while isinstance(obj, functools.partial): |
There was a problem hiding this comment.
Why don't we add an _unwrap_partial helper. Or.. should we maybe use inspect.unwrap() too?
There was a problem hiding this comment.
Actually, let's not use inspect.unwrap(). Decorating generators and coroutines isn't that common.
There was a problem hiding this comment.
Do we still want the helper?
There was a problem hiding this comment.
I have done the refactor in 3b841ac
Lib/test/test_inspect.py
Outdated
| import collections | ||
| import datetime | ||
| import functools | ||
| from functools import partial |
There was a problem hiding this comment.
Please use module import (i.e. import functools).
There was a problem hiding this comment.
Done in adb5db6. I did that originally to simplify the double functools.partial wrapping in the tests.
|
Hummmm, it seems that this changes the behaviour of def coroutine(func):
"""Decorator to mark coroutines.
If the coroutine is not yielded from before it is destroyed,
an error message is logged.
"""
if inspect.iscoroutinefunction(func):
# In Python 3.5 that's all we need to do for coroutines
# defined with "async def".
return func
if inspect.isgeneratorfunction(func):
coro = func
else:
@functools.wraps(func)
def coro(*args, **kw):this makes the function not being wrapped in @1st1 I don't know if this has a bit more impact than expected. Should I fix this by adding an extra check for |
1st1
left a comment
There was a problem hiding this comment.
Please remove new checks from asyncio.coroutine; AFAICT we don't need them.
Lib/asyncio/coroutines.py
Outdated
| """ | ||
| if inspect.iscoroutinefunction(func): | ||
| if (inspect.iscoroutinefunction(func) | ||
| and not isinstance(func, functools.partial)): |
There was a problem hiding this comment.
We don't need extra checks in this function. Here, we check for an async def coroutine -- we don't need to wrap them in a CoroWrapper ever.
Lib/asyncio/coroutines.py
Outdated
|
|
||
| if inspect.isgeneratorfunction(func): | ||
| if (inspect.isgeneratorfunction(func) | ||
| and not isinstance (func, functools.partial)): |
There was a problem hiding this comment.
We don't need this extra check either -- if func is a generator function, it means that we don't need to wrap it into a proxy to force it to return a generator.
|
When you're done making the requested changes, leave the comment: |
|
@1st1 If I remove those checks then https://github.com/python/cpython/blob/master/Lib/test/test_asyncio/test_tasks.py#L425 will fail because the partials are not wrapped anymore and the This is an example failure of that test for clarity: |
Lib/inspect.py
Outdated
| def _unwrap_partial(func): | ||
| while isinstance(func, functools.partial): | ||
| func = func.func | ||
| return func |
There was a problem hiding this comment.
I suggest to move this helper function to Lib/functools.py.
| @@ -0,0 +1,3 @@ | |||
| Make :func:`inspect.iscoroutinefunction`, | |||
| :func:`inspect.isgeneratorfunction` and :func:`inspect.isasyncgenfunction` | |||
| work with :func:`functools.partial`. Patch by Pablo Galindo. | |||
There was a problem hiding this comment.
Maybe also document the change with a ".. versionchanged:: 3.8" markup in https://docs.python.org/dev/library/inspect.html#inspect.isgeneratorfunction ?
|
(Oh, @1st1 already started to review this change, good ;-)) |
It's not a problem. Now that |
1st1
left a comment
There was a problem hiding this comment.
Sorry for the delayed review; I've been extremely busy last couple of weeks.
|
@1st1 Thank you very much for the review and the advice, Yuri! :) |
|
See also #6448 for a very related problem. |
| # Helper functions | ||
|
|
||
| def _unwrap_partial(func): | ||
| while isinstance(func, partial): |
There was a problem hiding this comment.
@pablogsal BTW this doesn't handle the case of partialmethod. Should we add that?
I have added some extra test cases for
isasyncgenfunctionandisasyncgenintest_iscoroutinefor symmetry, but I am not sure if that is the place for it. Tell me if I should reallocate these tests in other place.https://bugs.python.org/issue34890