Skip to content

Instantly share code, notes, and snippets.

@Bibo-Joshi
Created January 12, 2022 20:11
Show Gist options
  • Select an option

  • Save Bibo-Joshi/96f6b4642d749664145d429e386fb215 to your computer and use it in GitHub Desktop.

Select an option

Save Bibo-Joshi/96f6b4642d749664145d429e386fb215 to your computer and use it in GitHub Desktop.
Wrapper around `asyncio.iscoroutinefunction` that handles `functools.partial` on Python<=3.7 and also async `__call__` methods
import asyncio
import sys
from functools import partial
if sys.version_info >= (3, 8):
_MANUAL_UNWRAP = False
else:
_MANUAL_UNWRAP = True
def is_coroutine_function(obj: object) -> bool:
"""Thin wrapper around :func:`asyncio.iscoroutinefunction` that handles the support for
:func:`functools.partial` which :func:`asyncio.iscoroutinefunction` only natively supports in
Python 3.8+. Also handles callable classes, where ``__call__`` is async.
Note:
Can be removed once support for Python 3.7 is dropped.
Args:
obj (:class:`object`): The object to test.
Returns:
:obj:`bool`: Whether or not the object is a
`coroutine function <https://docs.python.org/3/library/asyncio-task.html#coroutine>`
"""
if not callable(obj):
return False
if _MANUAL_UNWRAP:
while isinstance(obj, partial):
obj = obj.func # type: ignore[attr-defined]
if not callable(obj):
return False
return asyncio.iscoroutinefunction(obj) or (
hasattr(obj, "__call__") and asyncio.iscoroutinefunction(obj.__call__)
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment