diff --git a/interactions/__init__.py b/interactions/__init__.py index c89a22d5c..b7a36d328 100644 --- a/interactions/__init__.py +++ b/interactions/__init__.py @@ -12,3 +12,4 @@ from .client import * # noqa: F401 F403 isort: skip from .api import * # noqa: F401 F403 from .base import * # noqa: F401 F403 +from .utils import * # noqa: F401 F403 diff --git a/interactions/api/gateway/client.py b/interactions/api/gateway/client.py index 53ad63e66..9af9f11c0 100644 --- a/interactions/api/gateway/client.py +++ b/interactions/api/gateway/client.py @@ -25,11 +25,11 @@ from ...base import get_logger from ...client.enums import InteractionType, OptionType from ...client.models import Option +from ...utils.missing import MISSING from ..dispatch import Listener from ..enums import OpCodeType from ..error import LibraryException from ..http.client import HTTPClient -from ..models.attrs_utils import MISSING from ..models.flags import Intents from ..models.guild import Guild from ..models.member import Member diff --git a/interactions/api/http/limiter.py b/interactions/api/http/limiter.py index 7b2f3f334..dc2e174e5 100644 --- a/interactions/api/http/limiter.py +++ b/interactions/api/http/limiter.py @@ -1,7 +1,7 @@ from asyncio import Lock from typing import Optional -from ..models.attrs_utils import MISSING +from ...utils.missing import MISSING __all__ = ("Limiter",) diff --git a/interactions/api/http/message.py b/interactions/api/http/message.py index 9706eece0..30f4abaae 100644 --- a/interactions/api/http/message.py +++ b/interactions/api/http/message.py @@ -3,7 +3,7 @@ from aiohttp import MultipartWriter from ...api.cache import Cache -from ..models.attrs_utils import MISSING +from ...utils.missing import MISSING from ..models.message import Embed, Message, Sticker from ..models.misc import AllowedMentions, File, Snowflake from .request import _Request diff --git a/interactions/api/http/webhook.py b/interactions/api/http/webhook.py index e6dbd793c..467c83f39 100644 --- a/interactions/api/http/webhook.py +++ b/interactions/api/http/webhook.py @@ -3,7 +3,7 @@ from aiohttp import MultipartWriter from ...api.cache import Cache -from ..models.attrs_utils import MISSING +from ...utils.missing import MISSING from ..models.misc import File from .request import _Request from .route import Route diff --git a/interactions/api/models/__init__.py b/interactions/api/models/__init__.py index 72dcb63c7..6cf9987d1 100644 --- a/interactions/api/models/__init__.py +++ b/interactions/api/models/__init__.py @@ -5,7 +5,6 @@ and stores all of the data defining models for dispatched Gateway events. """ -from .attrs_utils import * # noqa: F401 F403 from .audit_log import * # noqa: F401 F403 from .channel import * # noqa: F401 F403 from .emoji import * # noqa: F401 F403 diff --git a/interactions/api/models/audit_log.py b/interactions/api/models/audit_log.py index 20f01dd78..5c07cf98c 100644 --- a/interactions/api/models/audit_log.py +++ b/interactions/api/models/audit_log.py @@ -1,7 +1,7 @@ from enum import IntEnum from typing import TYPE_CHECKING, List, Optional, TypeVar -from .attrs_utils import DictSerializerMixin, convert_list, define, field +from ...utils.attrs_utils import DictSerializerMixin, convert_list, define, field from .channel import Channel from .misc import Snowflake from .user import User diff --git a/interactions/api/models/channel.py b/interactions/api/models/channel.py index 4acce6bca..ab4bbd7e9 100644 --- a/interactions/api/models/channel.py +++ b/interactions/api/models/channel.py @@ -2,15 +2,15 @@ from enum import IntEnum from typing import TYPE_CHECKING, Any, Callable, List, Optional, Union -from ..error import LibraryException -from .attrs_utils import ( - MISSING, +from ...utils.attrs_utils import ( ClientSerializerMixin, DictSerializerMixin, convert_list, define, field, ) +from ...utils.missing import MISSING +from ..error import LibraryException from .flags import Permissions from .misc import AllowedMentions, File, IDMixin, Overwrite, Snowflake from .user import User @@ -1241,7 +1241,7 @@ async def get_permissions_for(self, member: "Member") -> Permissions: return Permissions.ALL # @everyone role overwrites - from ...client.models.utils import search_iterable + from interactions.utils.utils import search_iterable overwrite_everyone = search_iterable( self.permission_overwrites, lambda overwrite: int(overwrite.id) == int(self.guild_id) diff --git a/interactions/api/models/emoji.py b/interactions/api/models/emoji.py index 625d9d9c3..6edeb29c9 100644 --- a/interactions/api/models/emoji.py +++ b/interactions/api/models/emoji.py @@ -1,7 +1,7 @@ from typing import TYPE_CHECKING, List, Optional, Union +from ...utils.attrs_utils import ClientSerializerMixin, convert_list, define, field from ..error import LibraryException -from .attrs_utils import ClientSerializerMixin, convert_list, define, field from .misc import Snowflake from .user import User diff --git a/interactions/api/models/guild.py b/interactions/api/models/guild.py index 05c14a122..918c4f1bc 100644 --- a/interactions/api/models/guild.py +++ b/interactions/api/models/guild.py @@ -2,15 +2,15 @@ from enum import Enum, IntEnum from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, Union -from ..error import LibraryException -from .attrs_utils import ( - MISSING, +from ...utils.attrs_utils import ( ClientSerializerMixin, DictSerializerMixin, convert_list, define, field, ) +from ...utils.missing import MISSING +from ..error import LibraryException from .audit_log import AuditLogEvents, AuditLogs from .channel import Channel, ChannelType, Thread, ThreadMember from .emoji import Emoji diff --git a/interactions/api/models/gw.py b/interactions/api/models/gw.py index f57ed1002..d2220ade2 100644 --- a/interactions/api/models/gw.py +++ b/interactions/api/models/gw.py @@ -1,7 +1,13 @@ from datetime import datetime from typing import Any, List, Optional -from .attrs_utils import ClientSerializerMixin, DictSerializerMixin, convert_list, define, field +from ...utils.attrs_utils import ( + ClientSerializerMixin, + DictSerializerMixin, + convert_list, + define, + field, +) from .channel import Channel, ThreadMember from .emoji import Emoji from .guild import EventMetadata diff --git a/interactions/api/models/member.py b/interactions/api/models/member.py index 91d42cde3..2fad32c91 100644 --- a/interactions/api/models/member.py +++ b/interactions/api/models/member.py @@ -1,9 +1,10 @@ from datetime import datetime from typing import TYPE_CHECKING, Any, List, Optional, Union -from ...client.models.utils import search_iterable +from ...utils.attrs_utils import ClientSerializerMixin, convert_int, convert_list, define, field +from ...utils.missing import MISSING +from ...utils.utils import search_iterable from ..error import LibraryException -from .attrs_utils import MISSING, ClientSerializerMixin, convert_int, convert_list, define, field from .channel import Channel from .flags import Permissions from .misc import AllowedMentions, File, IDMixin, Snowflake diff --git a/interactions/api/models/message.py b/interactions/api/models/message.py index 62625ad2f..04974f70d 100644 --- a/interactions/api/models/message.py +++ b/interactions/api/models/message.py @@ -5,9 +5,7 @@ from typing import TYPE_CHECKING, List, Optional, Union from ...client.models.component import ActionRow, Button, SelectMenu -from ..error import LibraryException -from .attrs_utils import ( - MISSING, +from ...utils.attrs_utils import ( ClientSerializerMixin, DictSerializerMixin, convert_list, @@ -16,6 +14,8 @@ define, field, ) +from ...utils.missing import MISSING +from ..error import LibraryException from .channel import Channel from .emoji import Emoji from .member import Member diff --git a/interactions/api/models/misc.py b/interactions/api/models/misc.py index 9ae635ce7..26e3c3ce3 100644 --- a/interactions/api/models/misc.py +++ b/interactions/api/models/misc.py @@ -15,8 +15,9 @@ from typing import List, Optional, Union from ...base import get_logger +from ...utils.attrs_utils import DictSerializerMixin, convert_list, define, field +from ...utils.missing import MISSING from ..error import LibraryException -from .attrs_utils import MISSING, DictSerializerMixin, convert_list, define, field __all__ = ( "AutoModKeywordPresetTypes", diff --git a/interactions/api/models/presence.py b/interactions/api/models/presence.py index 305774c64..c116ee701 100644 --- a/interactions/api/models/presence.py +++ b/interactions/api/models/presence.py @@ -2,7 +2,7 @@ from enum import IntEnum from typing import Any, List, Optional -from .attrs_utils import DictSerializerMixin, convert_list, define, field +from ...utils.attrs_utils import DictSerializerMixin, convert_list, define, field from .emoji import Emoji from .flags import StatusType from .misc import Snowflake diff --git a/interactions/api/models/role.py b/interactions/api/models/role.py index cb0bfbd41..b4d8ef42c 100644 --- a/interactions/api/models/role.py +++ b/interactions/api/models/role.py @@ -1,7 +1,8 @@ from typing import TYPE_CHECKING, Any, List, Optional, Union +from ...utils.attrs_utils import ClientSerializerMixin, DictSerializerMixin, define, field +from ...utils.missing import MISSING from ..error import LibraryException -from .attrs_utils import MISSING, ClientSerializerMixin, DictSerializerMixin, define, field from .misc import IDMixin, Image, Snowflake if TYPE_CHECKING: diff --git a/interactions/api/models/team.py b/interactions/api/models/team.py index e4bf3a827..d4dc6fe33 100644 --- a/interactions/api/models/team.py +++ b/interactions/api/models/team.py @@ -1,6 +1,6 @@ from typing import Any, List, Optional -from .attrs_utils import ClientSerializerMixin, convert_list, define, field +from ...utils.attrs_utils import ClientSerializerMixin, convert_list, define, field from .flags import AppFlags from .misc import IDMixin, Snowflake from .user import User diff --git a/interactions/api/models/user.py b/interactions/api/models/user.py index 5862745e7..7c6535cf2 100644 --- a/interactions/api/models/user.py +++ b/interactions/api/models/user.py @@ -1,6 +1,6 @@ from typing import TYPE_CHECKING, Optional, Union -from .attrs_utils import ClientSerializerMixin, define, field +from ...utils.attrs_utils import ClientSerializerMixin, define, field from .flags import UserFlags from .misc import IDMixin, Snowflake diff --git a/interactions/api/models/webhook.py b/interactions/api/models/webhook.py index 154d9eee4..7a50ff160 100644 --- a/interactions/api/models/webhook.py +++ b/interactions/api/models/webhook.py @@ -1,8 +1,9 @@ from enum import IntEnum from typing import TYPE_CHECKING, Any, List, Optional, Union +from ...utils.attrs_utils import ClientSerializerMixin, define, field +from ...utils.missing import MISSING from ..error import LibraryException -from .attrs_utils import MISSING, ClientSerializerMixin, define, field from .misc import AllowedMentions, File, IDMixin, Image, Snowflake from .user import User diff --git a/interactions/client/__init__.py b/interactions/client/__init__.py index 4e66cfab0..5d0b8cdba 100644 --- a/interactions/client/__init__.py +++ b/interactions/client/__init__.py @@ -8,5 +8,4 @@ from .context import * # noqa: F401 F403 from .decor import * # noqa: F401 F403 from .enums import * # noqa: F401 F403 -from .get import * # noqa: F401 F403 from .models import * # noqa: F401 F403 diff --git a/interactions/client/bot.py b/interactions/client/bot.py index ad2d29e2f..838904c12 100644 --- a/interactions/client/bot.py +++ b/interactions/client/bot.py @@ -13,7 +13,6 @@ from ..api import WebSocketClient as WSClient from ..api.error import LibraryException from ..api.http.client import HTTPClient -from ..api.models.attrs_utils import MISSING, convert_list from ..api.models.flags import Intents, Permissions from ..api.models.guild import Guild from ..api.models.misc import Image, Snowflake @@ -21,6 +20,8 @@ from ..api.models.team import Application from ..api.models.user import User from ..base import get_logger +from ..utils.attrs_utils import convert_list +from ..utils.missing import MISSING from .decor import component as _component from .enums import ApplicationCommandType, Locale, OptionType from .models.command import ApplicationCommand, Choice, Command, Option diff --git a/interactions/client/context.py b/interactions/client/context.py index 312faf2eb..b3cb4ca98 100644 --- a/interactions/client/context.py +++ b/interactions/client/context.py @@ -3,7 +3,6 @@ from ..api.error import LibraryException from ..api.http.client import HTTPClient -from ..api.models.attrs_utils import MISSING, ClientSerializerMixin, convert_int, define, field from ..api.models.channel import Channel from ..api.models.flags import Permissions from ..api.models.guild import Guild @@ -12,6 +11,8 @@ from ..api.models.misc import AllowedMentions, Snowflake from ..api.models.user import User from ..base import get_logger +from ..utils.attrs_utils import ClientSerializerMixin, convert_int, define, field +from ..utils.missing import MISSING from .enums import InteractionCallbackType, InteractionType from .models.command import Choice from .models.component import ActionRow, Button, Modal, SelectMenu, _build_components diff --git a/interactions/client/decor.py b/interactions/client/decor.py index e3063fe4b..1cb876ce1 100644 --- a/interactions/client/decor.py +++ b/interactions/client/decor.py @@ -1,8 +1,8 @@ from typing import Any, Dict, List, Optional, Union -from ..api.models.attrs_utils import MISSING from ..api.models.flags import Permissions from ..api.models.guild import Guild +from ..utils.missing import MISSING from .enums import ApplicationCommandType, Locale from .models.command import ApplicationCommand, Option from .models.component import Button, Component, SelectMenu diff --git a/interactions/client/models/__init__.py b/interactions/client/models/__init__.py index 940e80a30..27e80b668 100644 --- a/interactions/client/models/__init__.py +++ b/interactions/client/models/__init__.py @@ -8,4 +8,3 @@ from .command import * # noqa: F401 F403 from .component import * # noqa: F401 F403 from .misc import * # noqa: F401 F403 -from .utils import * # noqa: F401 F403 diff --git a/interactions/client/models/command.py b/interactions/client/models/command.py index 8f29d7bbb..5ad7d3006 100644 --- a/interactions/client/models/command.py +++ b/interactions/client/models/command.py @@ -4,7 +4,6 @@ from typing import TYPE_CHECKING, Any, Awaitable, Callable, Coroutine, Dict, List, Optional, Union from ...api.error import LibraryException -from ...api.models.attrs_utils import MISSING, DictSerializerMixin, convert_list, define, field from ...api.models.channel import Channel, ChannelType from ...api.models.guild import Guild from ...api.models.member import Member @@ -12,6 +11,8 @@ from ...api.models.misc import Snowflake from ...api.models.role import Role from ...api.models.user import User +from ...utils.attrs_utils import DictSerializerMixin, convert_list, define, field +from ...utils.missing import MISSING from ..enums import ApplicationCommandType, Locale, OptionType, PermissionType if TYPE_CHECKING: diff --git a/interactions/client/models/component.py b/interactions/client/models/component.py index 2d59978ab..77511cb4a 100644 --- a/interactions/client/models/component.py +++ b/interactions/client/models/component.py @@ -2,8 +2,9 @@ from typing import List, Optional, Union from ...api.error import LibraryException -from ...api.models.attrs_utils import MISSING, DictSerializerMixin, convert_list, define, field from ...api.models.emoji import Emoji +from ...utils.attrs_utils import DictSerializerMixin, convert_list, define, field +from ...utils.missing import MISSING from ..enums import ButtonStyle, ComponentType, TextStyleType __all__ = ( diff --git a/interactions/client/models/misc.py b/interactions/client/models/misc.py index aaba0f773..62f4aa9c8 100644 --- a/interactions/client/models/misc.py +++ b/interactions/client/models/misc.py @@ -1,12 +1,12 @@ from typing import Dict, List, Optional -from ...api.models.attrs_utils import DictSerializerMixin, convert_dict, convert_list, define, field from ...api.models.channel import Channel from ...api.models.member import Member from ...api.models.message import Attachment, Message from ...api.models.misc import Snowflake from ...api.models.role import Role from ...api.models.user import User +from ...utils.attrs_utils import DictSerializerMixin, convert_dict, convert_list, define, field from ..enums import ApplicationCommandType, ComponentType, InteractionType, PermissionType from ..models.command import Option from .component import ActionRow diff --git a/interactions/utils/__init__.py b/interactions/utils/__init__.py new file mode 100644 index 000000000..6c2e0f853 --- /dev/null +++ b/interactions/utils/__init__.py @@ -0,0 +1,4 @@ +from .attrs_utils import * # noqa: F401 F403 +from .get import * # noqa: F401 F403 +from .missing import * # noqa: F401 F403 +from .utils import * # noqa: F401 F403 diff --git a/interactions/api/models/attrs_utils.py b/interactions/utils/attrs_utils.py similarity index 92% rename from interactions/api/models/attrs_utils.py rename to interactions/utils/attrs_utils.py index 202994929..eb26b9bfa 100644 --- a/interactions/api/models/attrs_utils.py +++ b/interactions/utils/attrs_utils.py @@ -1,36 +1,15 @@ from copy import deepcopy from functools import wraps -from typing import ClassVar, Dict, Mapping, Optional, Tuple +from typing import Dict, Mapping, Optional, Tuple import attrs -__all__ = ("MISSING", "DictSerializerMixin", "ClientSerializerMixin") +from .missing import MISSING - -class _Missing: - """A sentinel object for places where None is a valid value""" - - _instance: ClassVar["_Missing"] = None - - def __new__(cls): - if not isinstance(cls._instance, cls): - cls._instance = object.__new__(cls) - return cls._instance - - def __eq__(self, other): - return self.__class__ is other.__class__ - - def __repr__(self): - return "" - - def __hash__(self): - return 0 - - def __bool__(self): - return False - - -MISSING = _Missing() +__all__ = ( + "DictSerializerMixin", + "ClientSerializerMixin", +) @attrs.define(eq=False, init=False, on_setattr=attrs.setters.NO_OP) diff --git a/interactions/api/models/attrs_utils.pyi b/interactions/utils/attrs_utils.pyi similarity index 87% rename from interactions/api/models/attrs_utils.pyi rename to interactions/utils/attrs_utils.pyi index ffde76d2f..7845f3c9a 100644 --- a/interactions/api/models/attrs_utils.pyi +++ b/interactions/utils/attrs_utils.pyi @@ -1,5 +1,5 @@ from functools import wraps -from typing import Any, Callable, ClassVar, Dict, List, Optional, Tuple, Type, TypeVar, Union, overload +from typing import Any, Callable, Dict, List, Optional, Tuple, Type, TypeVar, Union, overload import attrs @@ -9,22 +9,6 @@ _T = TypeVar("_T") _P = TypeVar("_P") -class _Missing: - """A sentinel object for places where None is a valid value""" - _instance: ClassVar["_Missing"] = None - - def __eq__(self, other): ... - - def __repr__(self): ... - - def __hash__(self): ... - - def __bool__(self): ... - - -MISSING = _Missing() - - @attrs.define(eq=False, init=False, on_setattr=attrs.setters.NO_OP) class DictSerializerMixin: _json: dict = attrs.field(init=False) diff --git a/interactions/client/get.py b/interactions/utils/get.py similarity index 95% rename from interactions/client/get.py rename to interactions/utils/get.py index ff64a6fa2..562651950 100644 --- a/interactions/client/get.py +++ b/interactions/utils/get.py @@ -2,7 +2,7 @@ from enum import Enum from inspect import isawaitable from logging import getLogger -from typing import Coroutine, List, Optional, Type, TypeVar, Union, get_args +from typing import TYPE_CHECKING, Coroutine, List, Optional, Type, TypeVar, Union, get_args try: from typing import _GenericAlias @@ -13,19 +13,20 @@ from sys import version_info from ..api.error import LibraryException -from ..api.http.client import HTTPClient from ..api.models.emoji import Emoji -from ..api.models.guild import Guild from ..api.models.member import Member from ..api.models.message import Message from ..api.models.misc import Snowflake from ..api.models.role import Role -from .bot import Client log = getLogger("get") _T = TypeVar("_T") +if TYPE_CHECKING: + from ..api.http.client import HTTPClient + from ..client.bot import Client + __all__ = ( "get", "Force", @@ -44,7 +45,7 @@ class Force(str, Enum): HTTP = "http" -def get(client: Client, obj: Type[_T], **kwargs) -> Optional[_T]: +def get(client: "Client", obj: Type[_T], **kwargs) -> Optional[_T]: """ Helper method to get an object. @@ -163,8 +164,6 @@ def get(client: Client, obj: Type[_T], **kwargs) -> Optional[_T]: If you enforce cache when getting a list of objects, found objets will be placed into the list and not found objects will be placed as ``None`` into the list. - - """ if version_info >= (3, 9): @@ -182,13 +181,14 @@ def _check(): return False if not isinstance(obj, type) and not isinstance(obj, _GenericAlias): - client: Client - obj: Union[Type[_T], Type[List[_T]]] raise LibraryException(message="The object must not be an instance of a class!", code=12) + client: "Client" + obj: Union[Type[_T], Type[List[_T]]] kwargs = _resolve_kwargs(obj, **kwargs) http_name = f"get_{obj.__name__.lower()}" kwarg_name = f"{obj.__name__.lower()}_id" + if isinstance(obj, _GenericAlias) or _check(): _obj: Type[_T] = get_args(obj)[0] _objects: List[Union[_obj, Coroutine]] = [] @@ -247,13 +247,15 @@ def _check(): async def _http_request( obj: Type[_T], - http: HTTPClient, + http: "HTTPClient", request: Union[Coroutine, List[Union[_T, Coroutine]], List[Coroutine]] = None, _name: str = None, **kwargs, ) -> Union[_T, List[_T]]: if not request: if obj in (Role, Emoji): + from ..api.models.guild import Guild + _guild = Guild(**await http.get_guild(kwargs.pop("guild_id")), _client=http) _func = getattr(_guild, _name) return await _func(**kwargs) @@ -276,7 +278,7 @@ async def _return_cache( def _get_cache( - _object: Type[_T], client: Client, kwarg_name: str, _list: bool = False, **kwargs + _object: Type[_T], client: "Client", kwarg_name: str, _list: bool = False, **kwargs ) -> Union[Optional[_T], List[Optional[_T]]]: if _list: _obj = [] diff --git a/interactions/client/get.pyi b/interactions/utils/get.pyi similarity index 100% rename from interactions/client/get.pyi rename to interactions/utils/get.pyi diff --git a/interactions/utils/missing.py b/interactions/utils/missing.py new file mode 100644 index 000000000..3f5b61aa4 --- /dev/null +++ b/interactions/utils/missing.py @@ -0,0 +1,29 @@ +from typing import ClassVar + +__all__ = ("MISSING",) + + +class _Missing: + """A sentinel object for places where None is a valid value""" + + _instance: ClassVar["_Missing"] = None + + def __new__(cls): + if not isinstance(cls._instance, cls): + cls._instance = object.__new__(cls) + return cls._instance + + def __eq__(self, other): + return self.__class__ is other.__class__ + + def __repr__(self): + return "" + + def __hash__(self): + return 0 + + def __bool__(self): + return False + + +MISSING = _Missing() diff --git a/interactions/client/models/utils.py b/interactions/utils/utils.py similarity index 94% rename from interactions/client/models/utils.py rename to interactions/utils/utils.py index 30316e0f5..4fd9054c4 100644 --- a/interactions/client/models/utils.py +++ b/interactions/utils/utils.py @@ -1,12 +1,12 @@ from asyncio import Task, get_running_loop, sleep from functools import wraps -from typing import TYPE_CHECKING, Awaitable, Callable, Iterable, List, Optional, TypeVar, Union +from typing import TYPE_CHECKING, Callable, Coroutine, Iterable, List, Optional, TypeVar, Union -from ...api.error import LibraryException -from .component import ActionRow, Button, Component, SelectMenu +from ..api.error import LibraryException +from ..client.models.component import ActionRow, Button, Component, SelectMenu if TYPE_CHECKING: - from ..context import CommandContext + from ..client.context import CommandContext __all__ = ("autodefer", "spread_to_rows", "search_iterable", "disable_components") @@ -17,7 +17,7 @@ def autodefer( delay: Union[float, int] = 2, ephemeral: bool = False, edit_origin: bool = False, -) -> Callable[[Callable[..., Awaitable]], Callable[..., Awaitable]]: +) -> Callable[[Callable[..., Coroutine]], Callable[..., Coroutine]]: """ A decorator that automatically defers a command if it did not respond within ``delay`` seconds. @@ -41,8 +41,8 @@ async def command(ctx): :rtype: """ - def decorator(coro: Callable[..., Awaitable]) -> Callable[..., Awaitable]: - from ..context import ComponentContext + def decorator(coro: Callable[..., Coroutine]) -> Callable[..., Coroutine]: + from ..client.context import ComponentContext @wraps(coro) async def deferring_func(ctx: Union["CommandContext", "ComponentContext"], *args, **kwargs):