This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: inspect.iscoroutinefunction / isgeneratorfunction / isasyncgenfunction can't handle partialmethod objects
Type: behavior Stage: patch review
Components: Library (Lib) Versions: Python 3.10, Python 3.9, Python 3.8
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: asvetlov, dreamsorcerer, jalaziz, mjpieters, yselivanov
Priority: normal Keywords: patch

Created on 2019-10-03 13:28 by mjpieters, last changed 2022-04-11 14:59 by admin.

Pull Requests
URL Status Linked Edit
PR 16600 open mjpieters, 2019-10-05 22:51
Messages (2)
msg353849 - (view) Author: Martijn Pieters (mjpieters) * Date: 2019-10-03 13:28
This is a follow-up to #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.<locals>._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
msg414598 - (view) Author: Jameel A. (jalaziz) Date: 2022-03-05 22:20
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.
History
Date User Action Args
2022-04-11 14:59:21adminsetgithub: 82545
2022-03-05 22:48:08jalazizsetversions: + Python 3.9, Python 3.10
2022-03-05 22:20:26jalazizsetnosy: + jalaziz
messages: + msg414598
2020-06-07 12:59:45dreamsorcerersetnosy: + dreamsorcerer
2019-10-05 22:51:55mjpieterssetkeywords: + patch
stage: patch review
pull_requests: + pull_request16188
2019-10-03 13:38:56xtreaksetnosy: + asvetlov, yselivanov
2019-10-03 13:28:44mjpieterscreate