Skip to content

Commit 5ffba32

Browse files
committed
Adjusted implementation and docs.
1 parent c073cf7 commit 5ffba32

File tree

3 files changed

+15
-17
lines changed

3 files changed

+15
-17
lines changed

Doc/library/inspect.rst

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -345,8 +345,7 @@ attributes (see :ref:`import-mod-attrs` for module attributes):
345345

346346
Return ``True`` if the object is a :term:`coroutine function` (a function
347347
defined with an :keyword:`async def` syntax), a :func:`functools.partial`
348-
wrapping a :term:`coroutine function`, an instance of a class defining an
349-
:keyword:`async def` ``__call__``, or a sync function marked with
348+
wrapping a :term:`coroutine function`, or a sync function marked with
350349
:func:`markcoroutinefunction`.
351350

352351
.. versionadded:: 3.5
@@ -356,8 +355,7 @@ attributes (see :ref:`import-mod-attrs` for module attributes):
356355
wrapped function is a :term:`coroutine function`.
357356

358357
.. versionchanged:: 3.12
359-
Instances of classes defining an :keyword:`async def` ``__call__``, or
360-
sync functions marked with :func:`markcoroutinefunction` now return
358+
Sync functions marked with :func:`markcoroutinefunction` now return
361359
``True``.
362360

363361

Lib/inspect.py

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,14 @@ def isgeneratorfunction(obj):
395395
# A marker for markcoroutinefunction and iscoroutinefunction.
396396
_is_coroutine_marker = object()
397397

398+
def _has_coroutine_mark(f):
399+
while ismethod(f):
400+
f = f.__func__
401+
f = functools._unwrap_partial(f)
402+
if not (isfunction(f) or _signature_is_functionlike(f)):
403+
return False
404+
return getattr(f, "_is_coroutine_marker", None) is _is_coroutine_marker
405+
398406
def markcoroutinefunction(func):
399407
"""
400408
Decorator to ensure callable is recognised as a coroutine function.
@@ -410,17 +418,7 @@ def iscoroutinefunction(obj):
410418
Coroutine functions are normally defined with "async def" syntax, but may
411419
be marked via markcoroutinefunction.
412420
"""
413-
if not isclass(obj) and callable(obj):
414-
# Test both the function and the __call__ implementation for the
415-
# _is_coroutine_marker.
416-
f = getattr(getattr(obj, "__func__", obj), "_is_coroutine_marker", None)
417-
c = getattr(obj.__call__, "_is_coroutine_marker", None)
418-
if f is _is_coroutine_marker or c is _is_coroutine_marker:
419-
return True
420-
421-
return _has_code_flag(obj, CO_COROUTINE) or (
422-
not isclass(obj) and callable(obj) and _has_code_flag(obj.__call__, CO_COROUTINE)
423-
)
421+
return _has_code_flag(obj, CO_COROUTINE) or _has_coroutine_mark(obj)
424422

425423
def isasyncgenfunction(obj):
426424
"""Return true if the object is an asynchronous generator function.

Lib/test/test_inspect.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -221,15 +221,17 @@ async def __call__(self):
221221
pass
222222

223223
self.assertFalse(inspect.iscoroutinefunction(Cl))
224-
self.assertTrue(inspect.iscoroutinefunction(Cl()))
224+
# instances with async def __call__ are NOT recognised.
225+
self.assertFalse(inspect.iscoroutinefunction(Cl()))
225226

226227
class Cl2:
227228
@inspect.markcoroutinefunction
228229
def __call__(self):
229230
pass
230231

231232
self.assertFalse(inspect.iscoroutinefunction(Cl2))
232-
self.assertTrue(inspect.iscoroutinefunction(Cl2()))
233+
# instances with marked __call__ are NOT recognised.
234+
self.assertFalse(inspect.iscoroutinefunction(Cl2()))
233235

234236
class Cl3:
235237
@inspect.markcoroutinefunction

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy