FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

bpo-34890: Make iscoroutinefunction, isgeneratorfunction and isasyncgenfunction work with functools.partial by pablogsal · Pull Request #9903 · python/cpython · GitHub

Repository navigation

bpo-34890: Make iscoroutinefunction, isgeneratorfunction and isasyncgenfunction work with functools.partial - #9903

Merged
pablogsal merged 8 commits into
python:masterfrom
pablogsal:bpo34890
Oct 26, 2018
Merged

pablogsal merged 8 commits into
python:masterfrom
pablogsal:bpo34890

Conversation

pablogsal commented Oct 15, 2018 •
edited by bedevere-bot
Loading

Copy link
Copy Markdown
Member

I have added some extra test cases for isasyncgenfunction and isasyncgen in test_iscoroutine for 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

pablogsal self-assigned this Oct 15, 2018
pablogsal requested review from 1st1 and asvetlov October 15, 2018 22:14
pablogsal changed the title Make iscoroutinefunction, isgeneratorfunction and isasyncgenfunction work with functools.partial bpo-34890: Make iscoroutinefunction, isgeneratorfunction and isasyncgenfunction work with functools.partial Oct 15, 2018
Comment thread 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

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

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.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Also, while you're here, please rename object to obj or o.

pablogsal commented Oct 15, 2018 •
edited
Loading

Copy link
Copy Markdown
Member Author

@1st1 Done in 41f7f60. Thanks for the review :)

Comment thread Lib/inspect.py Outdated
"""
return bool((isfunction(object) or ismethod(object)) and
object.__code__.co_flags & CO_ASYNC_GENERATOR)
while isinstance(obj, functools.partial):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Why don't we add an _unwrap_partial helper. Or.. should we maybe use inspect.unwrap() too?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Actually, let's not use inspect.unwrap(). Decorating generators and coroutines isn't that common.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Do we still want the helper?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I have done the refactor in 3b841ac

Comment thread Lib/test/test_inspect.py Outdated
import collections
import datetime
import functools
from functools import partial

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Please use module import (i.e. import functools).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Done in adb5db6. I did that originally to simplify the double functools.partial wrapping in the tests.

pablogsal commented Oct 15, 2018 •
edited
Loading

Copy link
Copy Markdown
Member Author

Hummmm, it seems that this changes the behaviour of coroutine in Lib/asyncio/coroutines.py:

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 CoroWrapper anymore.

@1st1 I don't know if this has a bit more impact than expected. Should I fix this by adding an extra check for partial in coroutine() (check commit 617688e to see what I mean), or should we approach this differently?

1st1 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Please remove new checks from asyncio.coroutine; AFAICT we don't need them.

Comment thread Lib/asyncio/coroutines.py Outdated
"""
if inspect.iscoroutinefunction(func):
if (inspect.iscoroutinefunction(func)
and not isinstance(func, functools.partial)):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

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.

Comment thread Lib/asyncio/coroutines.py Outdated

if inspect.isgeneratorfunction(func):
if (inspect.isgeneratorfunction(func)
and not isinstance (func, functools.partial)):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

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.

Copy link
Copy Markdown

When you're done making the requested changes, leave the comment: I have made the requested changes; please review again.

pablogsal commented Oct 16, 2018 •
edited
Loading

Copy link
Copy Markdown
Member Author

@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 __reprl__ will be different. I was not sure if this would be a problem or not (notice commit 617688e was just to show what I mean with "fix this by adding an extra check for partial in coroutine()" in my previous comment). Should I change the tests now that we don't need to wrap these (proposal of that change in commit caddd21)?

This is an example failure of that test for clarity:

======================================================================
FAIL: test_task_repr_partial_corowrapper (test.test_asyncio.test_tasks.PyTask_PyFuture_Tests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/pablogsal/github/cpython/Lib/test/test_asyncio/test_tasks.py", line 446, in test_task_repr_partial_corowrapper
    self.assertRegex(coro_repr, expected)
AssertionError: Regex didn't match: '<CoroWrapper \\w+.test_task_repr_partial_corowrapper\\.<locals>\\.func\\(1\\)\\(\\) running, ' not found in '<coroutine object BaseTaskTests.test_task_repr_partial_corowrapper.<locals>.func at 0x7f30c10b9788>'

----------------------------------------------------------------------

vstinner left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I like the overall change.

@1st1: Would you mind to review this change?

Comment thread Lib/inspect.py Outdated
def _unwrap_partial(func):
while isinstance(func, functools.partial):
func = func.func
return func

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

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.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Maybe also document the change with a ".. versionchanged:: 3.8" markup in https://docs.python.org/dev/library/inspect.html#inspect.isgeneratorfunction ?

Copy link
Copy Markdown
Member

(Oh, @1st1 already started to review this change, good ;-))

pablogsal requested a review from rhettinger as a code owner October 25, 2018 22:29

vstinner left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

LGTM, but I would prefer to see a second review from a core (@1st1 maybe?).

1st1 commented Oct 26, 2018

Copy link
Copy Markdown
Member

@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 reprl will be different. I was not sure if this would be a problem or not

It's not a problem. Now that inspect.isgeneratorfunction works with functools.partial we no longer need to wrap partial objects in a proxy generator "just in case".

1st1 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Sorry for the delayed review; I've been extremely busy last couple of weeks.

pablogsal merged commit 7cd2543 into python:master Oct 26, 2018
pablogsal deleted the bpo34890 branch October 26, 2018 11:19

Copy link
Copy Markdown
Member Author

@1st1 Thank you very much for the review and the advice, Yuri! :)

jdemeyer commented Nov 5, 2018 •
edited
Loading

Copy link
Copy Markdown
Contributor

See also #6448 for a very related problem.

Comment thread Lib/functools.py
# Helper functions

def _unwrap_partial(func):
while isinstance(func, partial):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

@pablogsal BTW this doesn't handle the case of partialmethod. Should we add that?

This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants


Back | FazBrowse Home | New Git URL