@@ -395,6 +395,14 @@ def isgeneratorfunction(obj):
395
395
# A marker for markcoroutinefunction and iscoroutinefunction.
396
396
_is_coroutine_marker = object ()
397
397
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
+
398
406
def markcoroutinefunction (func ):
399
407
"""
400
408
Decorator to ensure callable is recognised as a coroutine function.
@@ -410,17 +418,7 @@ def iscoroutinefunction(obj):
410
418
Coroutine functions are normally defined with "async def" syntax, but may
411
419
be marked via markcoroutinefunction.
412
420
"""
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 )
424
422
425
423
def isasyncgenfunction (obj ):
426
424
"""Return true if the object is an asynchronous generator function.
0 commit comments