Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

inspect.iscoroutinefunction / isgeneratorfunction / isasyncgenfunction can't handle partialmethod objects #82545

Open
mjpieters mannequin opened this issue Oct 3, 2019 · 5 comments
Labels
3.8 only security fixes 3.9 only security fixes 3.10 only security fixes stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error

Comments

@mjpieters
Copy link
Mannequin

mjpieters mannequin commented Oct 3, 2019

BPO 38364
Nosy @mjpieters, @asvetlov, @1st1, @Dreamsorcerer, @jalaziz
PRs
  • bpo-38364: unwrap partialmethods just like we unwrap partials #16600
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = None
    closed_at = None
    created_at = <Date 2019-10-03.13:28:44.060>
    labels = ['3.8', 'type-bug', 'library', '3.9', '3.10']
    title = "inspect.iscoroutinefunction / isgeneratorfunction / isasyncgenfunction can't handle  partialmethod objects"
    updated_at = <Date 2022-03-05.22:48:08.143>
    user = 'https://github.com/mjpieters'

    bugs.python.org fields:

    activity = <Date 2022-03-05.22:48:08.143>
    actor = 'jalaziz'
    assignee = 'none'
    closed = False
    closed_date = None
    closer = None
    components = ['Library (Lib)']
    creation = <Date 2019-10-03.13:28:44.060>
    creator = 'mjpieters'
    dependencies = []
    files = []
    hgrepos = []
    issue_num = 38364
    keywords = ['patch']
    message_count = 2.0
    messages = ['353849', '414598']
    nosy_count = 5.0
    nosy_names = ['mjpieters', 'asvetlov', 'yselivanov', 'dreamsorcerer', 'jalaziz']
    pr_nums = ['16600']
    priority = 'normal'
    resolution = None
    stage = 'patch review'
    status = 'open'
    superseder = None
    type = 'behavior'
    url = 'https://bugs.python.org/issue38364'
    versions = ['Python 3.8', 'Python 3.9', 'Python 3.10']

    @mjpieters
    Copy link
    Mannequin Author

    mjpieters mannequin commented Oct 3, 2019

    This is a follow-up to bpo-33261, which added general support for detecting generator / coroutine / async generator functions wrapped in partials. It appears that partialmethod objects were missed out.

    While a partialmethod object will produce a functools.partial() object on binding to an instance, the .func attribute of that partial is a bound method, not a function, and the current _has_code_flag implementation unwraps methods *before* it unwraps partials.

    Next, binding to a class produces a partialmethod._make_unbound_method.._method wrapper function. _unwrap_partial can't unwrap this, as it doesn't handle this case; it could look for the _partialmethod attribute and follow that to find the .func attribute.

    Test case:

    import inspect
    import functools
    
    class Foo:
        async def bar(self, a): return a
        ham = partialmethod(bar, "spam")
    
    print(inspect.iscoroutinefunction(Foo.bar)  # True
    print(inspect.iscoroutinefunction(Foo.ham)  # False
    instance = Foo()
    print(inspect.iscoroutinefunction(instance.bar)  # True
    print(inspect.iscoroutinefunction(instance.ham)  # False

    @mjpieters mjpieters mannequin added 3.8 only security fixes stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error labels Oct 3, 2019
    @jalaziz
    Copy link
    Mannequin

    jalaziz mannequin commented Mar 5, 2022

    I've recently ran into this via unittest.mock.patch.object. Mocking an asynchronous partial method returns MagicMock and not AsyncMagicMock, causing some pretty hard to debug failures.

    @jalaziz jalaziz mannequin added 3.9 only security fixes 3.10 only security fixes labels Mar 5, 2022
    @ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
    @graingert
    Copy link
    Contributor

    see also #67707

    @pavelm10
    Copy link

    pavelm10 commented Dec 1, 2022

    The above test case slightly changed:

    def test_dummy():
        import inspect
        import functools
    
        class Foo:
            async def bar(self, a): return a
            ham = functools.partialmethod(bar, "spam")
    
        assert inspect.iscoroutinefunction(Foo.bar)  # True
        assert not inspect.iscoroutinefunction(Foo.ham)  # False
        instance = Foo()
        assert inspect.iscoroutinefunction(instance.bar)  # True
        assert inspect.iscoroutinefunction(instance.ham)  # False

    IS NOT failing for Python 3.10.7
    IS failing for Python 3.10.2
    Other 3.10.x not tested.

    @mjpieters
    Copy link
    Contributor

    The above test case slightly changed:

        assert inspect.iscoroutinefunction(Foo.bar)  # True
        assert not inspect.iscoroutinefunction(Foo.ham)  # False

    Why did you change the test to add not?

    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    3.8 only security fixes 3.9 only security fixes 3.10 only security fixes stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error
    Projects
    None yet
    Development

    No branches or pull requests

    3 participants