python / python/cpython

`inspect.iscoroutinefunction()` does not detect marked partial objects

未關閉
#142,418 4 則留言 0 個 reaction 已指派 0 人 在 GitHub 檢視

還沒有人認領這個 Issue。

stdlib type-bug
主要語言
Python
星號
77.2k
分支
36k
PR 合併指標
PR 指標待擷取

描述

Bug report

Bug description:

inspect.markcoroutinefunction() is applied directly to the passed function, except for methods (which is correct behavior). However, inspect.iscoroutinefunction() checks the passed function only after unwrapping (a function that is not wrapped in either functools.partial or functools.partialmethod (currently, _has_coroutine_mark() does not handle these objects; why?)), and thus cannot detect the marker that is not at the end of the unwrapping chain, which results in false negative in cases where a functools.partial/functools.partialmethod object is marked.

>>> from functools import partial
>>> from inspect import iscoroutinefunction, markcoroutinefunction
>>> async def wedonotlikesnakecase():
...     return "the_funniest_joke_in_the_world"
>>> def manufacturer_of_jokes(somefunc):
...     global manufacturer_of_jokes
...     del manufacturer_of_jokes
...     return somefunc()
>>> joke = partial(manufacturer_of_jokes, wedonotlikesnakecase)
>>> joke = markcoroutinefunction(joke)
>>> iscoroutinefunction(joke)
False

I discovered this problem while theoretically considering backporting inspect.iscoroutinefunction() to older versions of Python. The problem has not yet been caused by any use case, so it is okay if the issue is closed due to lack of demand. But just in case, I am attaching part of how iscoroutinefunction() is implemented in my code.

def iscoroutinefunction(obj):
    marker_name, marker_value = _get_coroutinefunction_marker()

    while True:  # unwrap & check
        if ismethod(obj):
            obj = obj.__func__
            continue

        if marker_value is not MISSING:
            if getattr(obj, marker_name, MISSING) is marker_value:
                return True

        if isinstance(obj, partial):
            obj = obj.func
            continue

        impl = getattr(obj, _partialmethod_attribute_name, MISSING)

        if isinstance(impl, partialmethod):
            obj = impl.func
            continue

        # unlike its namesake in the `inspect` module, it does not unwrap
        return _has_code_flag(obj, CO_COROUTINE)
CPython versions tested on:

3.12, 3.13, 3.14

Operating systems tested on:

Linux

Linked PRs
  • gh-142503
  • gh-142505

貢獻指南

開啟貢獻指南

從這裡開始

  1. 先讀完整個 Issue,再讀專案的貢獻指南。
  2. 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
  3. Fork 儲存庫,在一個分支上完成修改。
  4. 送出 Pull Request,並在描述裡引用這個 Issue 編號。

研究方向

從 inspect.iscoroutinefunction()、inspect.markcoroutinefunction() 和 _has_coroutine_mark() 開始,使用 issue 中的重現程式確認對已標記 functools.partial 的誤判漏檢。開始前先查看已連結的 PR gh-142503 和 gh-142505;完成的標準是能正確偵測報告中的 partial-object 情況,同時不回歸現有的方法和解包行為。

由索引模型根據 Issue 內容生成。

評估

技術堆疊
python
領域
backend
Issue 類型
缺陷
難度
3/5
預估耗時
1-2 天
活躍度
停滯
描述清晰度
描述清楚
新手友好度
35/100

把新 issue 寄到你的電子郵件信箱

精選適合新手參與的 GitHub issue 摘要。