python / python/cpython

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

Offen
#142,418 4 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

stdlib type-bug
Vorherrschende Sprache
Python
Sterne
77.2k
Forks
35.9k
PR-Merge-Kennzahlen
PR-Kennzahlen ausstehend

Beschreibung

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

Beitragsleitfaden

Beitragsleitfaden öffnen

Erste Schritte

  1. Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
  3. Forke das Repository und arbeite in einem Branch.
  4. Öffne einen Pull Request, der die Issue-Nummer nennt.

Rechercherichtung

Beginne mit inspect.iscoroutinefunction(), inspect.markcoroutinefunction() und _has_coroutine_mark() und verwende den Reproducer im Issue, um den False Negative für ein markiertes functools.partial zu bestätigen. Prüfe die verknüpften PRs gh-142503 und gh-142505, bevor du beginnst; abgeschlossen ist die Aufgabe, wenn der gemeldete Fall eines partial-Objekts korrekt erkannt wird, ohne das bestehende Verhalten für Methoden und das Unwrapping zu beeinträchtigen.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
python
Bereich
backend
Issue-Typ
Bug
Schwierigkeit
3/5
Geschätzter Aufwand
1-2 Tage
Aktivitätsstatus
Veraltet
Klarheit
Klar beschrieben
Anfängerfreundlichkeit
35/100

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.