diff --git a/Lib/asyncio/coroutines.py b/Lib/asyncio/coroutines.py index 7fda0e449d500a..7bd5ba4ba92484 100644 --- a/Lib/asyncio/coroutines.py +++ b/Lib/asyncio/coroutines.py @@ -19,8 +19,11 @@ def _is_debug_mode(): def iscoroutinefunction(func): """Return True if func is a decorated coroutine function.""" - return (inspect.iscoroutinefunction(func) or - getattr(func, '_is_coroutine', None) is _is_coroutine) + return ( + inspect.iscoroutinefunction(func) + or getattr(func, '_is_coroutine', None) is _is_coroutine + or getattr(functools._unwrap_partial(func), "_is_coroutine", None) is _is_coroutine + ) # Prioritize native coroutine check to speed-up diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py index bde4defdf0129e..31db756fc8bf5b 100644 --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -1644,9 +1644,27 @@ def fn1(): yield self.assertFalse(asyncio.iscoroutinefunction(fn1)) - async def fn2(): + def fn2(): pass + + fn2._is_coroutine = asyncio.coroutines._is_coroutine + self.assertTrue(asyncio.iscoroutinefunction(fn2)) + self.assertTrue(asyncio.iscoroutinefunction(functools.partial(fn2))) + self.assertTrue(asyncio.iscoroutinefunction(functools.partial(functools.partial(fn2)))) + + async def async_fn(): + pass + + self.assertTrue(asyncio.iscoroutinefunction(afn2)) + + def sync_fn(): + pass + + partial_sync_fn = functools.partial(sync_fn) + partial_sync_fn._is_coroutine = asyncio.coroutines._is_coroutine + + self.assertTrue(asyncio.iscoroutinefunction(partial_sync_fn)) self.assertFalse(asyncio.iscoroutinefunction(mock.Mock())) self.assertTrue(asyncio.iscoroutinefunction(mock.AsyncMock()))