From bc724a83f29cf284032156e1934d86bb6398b87e Mon Sep 17 00:00:00 2001 From: Jakub Kuczys Date: Tue, 14 Apr 2026 15:34:10 +0200 Subject: [PATCH] Use iscoroutinefunction from inspect instead of asyncio on 3.12+ --- discord/client.py | 4 ++-- discord/ext/commands/bot.py | 9 ++++----- discord/ext/commands/core.py | 8 ++++---- discord/utils.py | 9 +++++++++ 4 files changed, 19 insertions(+), 11 deletions(-) diff --git a/discord/client.py b/discord/client.py index 1c1ed9f48..cc77ae5f8 100644 --- a/discord/client.py +++ b/discord/client.py @@ -68,7 +68,7 @@ from .voice_client import VoiceClient from .http import HTTPClient from .state import ConnectionState from . import utils -from .utils import MISSING, time_snowflake, deprecated +from .utils import MISSING, time_snowflake, deprecated, _iscoroutinefunction from .object import Object from .backoff import ExponentialBackoff from .webhook import Webhook @@ -2098,7 +2098,7 @@ class Client: The coroutine passed is not actually a coroutine. """ - if not asyncio.iscoroutinefunction(coro): + if not _iscoroutinefunction(coro): raise TypeError('event registered must be a coroutine function') setattr(self, coro.__name__, coro) diff --git a/discord/ext/commands/bot.py b/discord/ext/commands/bot.py index 0bb4cf95f..46b5f5850 100644 --- a/discord/ext/commands/bot.py +++ b/discord/ext/commands/bot.py @@ -25,7 +25,6 @@ DEALINGS IN THE SOFTWARE. from __future__ import annotations -import asyncio import collections import collections.abc import inspect @@ -53,7 +52,7 @@ from typing import ( import discord from discord import app_commands from discord.app_commands.tree import _retrieve_guild_ids -from discord.utils import MISSING, _is_submodule +from discord.utils import MISSING, _iscoroutinefunction, _is_submodule from .core import GroupMixin from .view import StringView @@ -581,7 +580,7 @@ class BotBase(GroupMixin[None]): TypeError The coroutine passed is not actually a coroutine. """ - if not asyncio.iscoroutinefunction(coro): + if not _iscoroutinefunction(coro): raise TypeError('The pre-invoke hook must be a coroutine.') self._before_invoke = coro @@ -618,7 +617,7 @@ class BotBase(GroupMixin[None]): TypeError The coroutine passed is not actually a coroutine. """ - if not asyncio.iscoroutinefunction(coro): + if not _iscoroutinefunction(coro): raise TypeError('The post-invoke hook must be a coroutine.') self._after_invoke = coro @@ -654,7 +653,7 @@ class BotBase(GroupMixin[None]): """ name = func.__name__ if name is MISSING else name - if not asyncio.iscoroutinefunction(func): + if not _iscoroutinefunction(func): raise TypeError('Listeners must be coroutines') if name in self.extra_events: diff --git a/discord/ext/commands/core.py b/discord/ext/commands/core.py index 949539b61..1116c81e9 100644 --- a/discord/ext/commands/core.py +++ b/discord/ext/commands/core.py @@ -427,7 +427,7 @@ class Command(_BaseCommand, Generic[CogT, P, T]): /, **kwargs: Unpack[_CommandKwargs], ) -> None: - if not asyncio.iscoroutinefunction(func): + if not discord.utils._iscoroutinefunction(func): raise TypeError('Callback must be a coroutine.') name = kwargs.get('name') or func.__name__ @@ -1102,7 +1102,7 @@ class Command(_BaseCommand, Generic[CogT, P, T]): The coroutine passed is not actually a coroutine. """ - if not asyncio.iscoroutinefunction(coro): + if not discord.utils._iscoroutinefunction(coro): raise TypeError('The error handler must be a coroutine.') self.on_error: Error[CogT, Any] = coro @@ -1140,7 +1140,7 @@ class Command(_BaseCommand, Generic[CogT, P, T]): TypeError The coroutine passed is not actually a coroutine. """ - if not asyncio.iscoroutinefunction(coro): + if not discord.utils._iscoroutinefunction(coro): raise TypeError('The pre-invoke hook must be a coroutine.') self._before_invoke = coro @@ -1171,7 +1171,7 @@ class Command(_BaseCommand, Generic[CogT, P, T]): TypeError The coroutine passed is not actually a coroutine. """ - if not asyncio.iscoroutinefunction(coro): + if not discord.utils._iscoroutinefunction(coro): raise TypeError('The post-invoke hook must be a coroutine.') self._after_invoke = coro diff --git a/discord/utils.py b/discord/utils.py index ba7bdd3e1..b4738a2b3 100644 --- a/discord/utils.py +++ b/discord/utils.py @@ -26,6 +26,7 @@ from __future__ import annotations import array import asyncio +import inspect from textwrap import TextWrapper from typing import ( Any, @@ -1542,3 +1543,11 @@ class _RawReprMixin: def __repr__(self) -> str: value = ' '.join(f'{attr}={getattr(self, attr)!r}' for attr in self.__slots__) return f'<{self.__class__.__name__} {value}>' + + +# `inspect.iscoroutinefunction()` only became equivalent to (now deprecated) `inspect.iscoroutinefunction()` in Python 3.12 +# https://github.com/python/cpython/issues/122858#issuecomment-2466239748 +if sys.version_info >= (3, 12): + _iscoroutinefunction = inspect.iscoroutinefunction +else: + _iscoroutinefunction = asyncio.iscoroutinefunction