diff --git a/disnake/app_commands.py b/disnake/app_commands.py index 727f35cb93..0369cb0dc7 100644 --- a/disnake/app_commands.py +++ b/disnake/app_commands.py @@ -262,7 +262,7 @@ def __init__( type: Optional[Union[OptionType, int]] = None, required: bool = False, choices: Optional[Choices] = None, - options: Optional[list] = None, + options: Optional[List[Option]] = None, channel_types: Optional[List[ChannelType]] = None, autocomplete: bool = False, min_value: Optional[float] = None, @@ -392,7 +392,7 @@ def add_option( type: Optional[OptionType] = None, required: bool = False, choices: Optional[Choices] = None, - options: Optional[list] = None, + options: Optional[List[Option]] = None, channel_types: Optional[List[ChannelType]] = None, autocomplete: bool = False, min_value: Optional[float] = None, @@ -888,7 +888,7 @@ def add_option( type: Optional[OptionType] = None, required: bool = False, choices: Optional[Choices] = None, - options: Optional[list] = None, + options: Optional[List[Option]] = None, channel_types: Optional[List[ChannelType]] = None, autocomplete: bool = False, min_value: Optional[float] = None, diff --git a/disnake/asset.py b/disnake/asset.py index ad83b12fe2..de6b48ef69 100644 --- a/disnake/asset.py +++ b/disnake/asset.py @@ -64,7 +64,10 @@ async def read(self) -> bytes: return await self._state.http.get_from_cdn(self.url) async def save( - self, fp: Union[str, bytes, os.PathLike, io.BufferedIOBase], *, seek_begin: bool = True + self, + fp: Union[str, bytes, os.PathLike[str], os.PathLike[bytes], io.BufferedIOBase], + *, + seek_begin: bool = True, ) -> int: """|coro| diff --git a/disnake/channel.py b/disnake/channel.py index 8eaf8dd794..b7cb1c7459 100644 --- a/disnake/channel.py +++ b/disnake/channel.py @@ -3404,7 +3404,7 @@ async def create_thread( stickers: Sequence[Union[GuildSticker, StandardSticker, StickerItem]] = ..., allowed_mentions: AllowedMentions = ..., view: View = ..., - components: Components = ..., + components: Components[MessageUIComponent] = ..., reason: Optional[str] = None, ) -> ThreadWithMessage: ... @@ -3425,7 +3425,7 @@ async def create_thread( stickers: Sequence[Union[GuildSticker, StandardSticker, StickerItem]] = ..., allowed_mentions: AllowedMentions = ..., view: View = ..., - components: Components = ..., + components: Components[MessageUIComponent] = ..., reason: Optional[str] = None, ) -> ThreadWithMessage: ... @@ -3446,7 +3446,7 @@ async def create_thread( stickers: Sequence[Union[GuildSticker, StandardSticker, StickerItem]] = ..., allowed_mentions: AllowedMentions = ..., view: View = ..., - components: Components = ..., + components: Components[MessageUIComponent] = ..., reason: Optional[str] = None, ) -> ThreadWithMessage: ... @@ -3467,7 +3467,7 @@ async def create_thread( stickers: Sequence[Union[GuildSticker, StandardSticker, StickerItem]] = ..., allowed_mentions: AllowedMentions = ..., view: View = ..., - components: Components = ..., + components: Components[MessageUIComponent] = ..., reason: Optional[str] = None, ) -> ThreadWithMessage: ... diff --git a/disnake/client.py b/disnake/client.py index 0fed3eb8e4..2caa3282ae 100644 --- a/disnake/client.py +++ b/disnake/client.py @@ -424,12 +424,14 @@ def __init__( loop=self.loop, ) - self._handlers: Dict[str, Callable] = { + self._handlers: Dict[str, Callable[..., Any]] = { "ready": self._handle_ready, "connect_internal": self._handle_first_connect, } - self._hooks: Dict[str, Callable] = {"before_identify": self._call_before_identify_hook} + self._hooks: Dict[str, Callable[..., Any]] = { + "before_identify": self._call_before_identify_hook + } self._enable_debug_events: bool = enable_debug_events self._enable_gateway_error_handler: bool = enable_gateway_error_handler diff --git a/disnake/errors.py b/disnake/errors.py index 416a32d7f1..c8e58c1d68 100644 --- a/disnake/errors.py +++ b/disnake/errors.py @@ -315,7 +315,7 @@ class InteractionException(ClientException): The interaction that was responded to. """ - interaction: Interaction + interaction: Interaction[Any] class InteractionTimedOut(InteractionException): @@ -330,8 +330,8 @@ class InteractionTimedOut(InteractionException): The interaction that was responded to. """ - def __init__(self, interaction: Interaction) -> None: - self.interaction: Interaction = interaction + def __init__(self, interaction: Interaction[Any]) -> None: + self.interaction: Interaction[Any] = interaction msg = ( "Interaction took more than 3 seconds to be responded to. " @@ -359,8 +359,8 @@ class InteractionResponded(InteractionException): The interaction that's already been responded to. """ - def __init__(self, interaction: Interaction) -> None: - self.interaction: Interaction = interaction + def __init__(self, interaction: Interaction[Any]) -> None: + self.interaction: Interaction[Any] = interaction super().__init__("This interaction has already been responded to before") @@ -378,8 +378,8 @@ class InteractionNotResponded(InteractionException): The interaction that hasn't been responded to. """ - def __init__(self, interaction: Interaction) -> None: - self.interaction: Interaction = interaction + def __init__(self, interaction: Interaction[Any]) -> None: + self.interaction: Interaction[Any] = interaction super().__init__("This interaction hasn't been responded to yet") @@ -394,8 +394,8 @@ class ModalChainNotSupported(InteractionException): The interaction that was responded to. """ - def __init__(self, interaction: ModalInteraction) -> None: - self.interaction: ModalInteraction = interaction + def __init__(self, interaction: ModalInteraction[Any]) -> None: + self.interaction: ModalInteraction[Any] = interaction super().__init__("You cannot respond to a modal with another modal.") @@ -411,8 +411,8 @@ class InteractionNotEditable(InteractionException): The interaction that was responded to. """ - def __init__(self, interaction: Interaction) -> None: - self.interaction: Interaction = interaction + def __init__(self, interaction: Interaction[Any]) -> None: + self.interaction: Interaction[Any] = interaction super().__init__("This interaction does not have a message to edit.") diff --git a/disnake/ext/commands/base_core.py b/disnake/ext/commands/base_core.py index ef46210495..38420a8abf 100644 --- a/disnake/ext/commands/base_core.py +++ b/disnake/ext/commands/base_core.py @@ -37,7 +37,7 @@ from .cog import Cog ApplicationCommandInteractionT = TypeVar( - "ApplicationCommandInteractionT", bound=ApplicationCommandInteraction, covariant=True + "ApplicationCommandInteractionT", bound=ApplicationCommandInteraction[Any], covariant=True ) P = ParamSpec("P") @@ -282,7 +282,7 @@ def remove_check(self, func: AppCheck) -> None: pass async def __call__( - self, interaction: ApplicationCommandInteraction, *args: Any, **kwargs: Any + self, interaction: ApplicationCommandInteraction[Any], *args: Any, **kwargs: Any ) -> Any: """|coro| @@ -300,7 +300,7 @@ async def __call__( else: return await self.callback(interaction, *args, **kwargs) - def _prepare_cooldowns(self, inter: ApplicationCommandInteraction) -> None: + def _prepare_cooldowns(self, inter: ApplicationCommandInteraction[Any]) -> None: if self._buckets.valid: dt = inter.created_at current = dt.replace(tzinfo=datetime.timezone.utc).timestamp() @@ -310,7 +310,7 @@ def _prepare_cooldowns(self, inter: ApplicationCommandInteraction) -> None: if retry_after: raise CommandOnCooldown(bucket, retry_after, self._buckets.type) # type: ignore - async def prepare(self, inter: ApplicationCommandInteraction) -> None: + async def prepare(self, inter: ApplicationCommandInteraction[Any]) -> None: inter.application_command = self if not await self.can_run(inter): @@ -327,7 +327,7 @@ async def prepare(self, inter: ApplicationCommandInteraction) -> None: await self._max_concurrency.release(inter) # type: ignore raise - def is_on_cooldown(self, inter: ApplicationCommandInteraction) -> bool: + def is_on_cooldown(self, inter: ApplicationCommandInteraction[Any]) -> bool: """Checks whether the application command is currently on cooldown. Parameters @@ -348,7 +348,7 @@ def is_on_cooldown(self, inter: ApplicationCommandInteraction) -> bool: current = dt.replace(tzinfo=datetime.timezone.utc).timestamp() return bucket.get_tokens(current) == 0 - def reset_cooldown(self, inter: ApplicationCommandInteraction) -> None: + def reset_cooldown(self, inter: ApplicationCommandInteraction[Any]) -> None: """Resets the cooldown on this application command. Parameters @@ -360,7 +360,7 @@ def reset_cooldown(self, inter: ApplicationCommandInteraction) -> None: bucket = self._buckets.get_bucket(inter) # type: ignore bucket.reset() - def get_cooldown_retry_after(self, inter: ApplicationCommandInteraction) -> float: + def get_cooldown_retry_after(self, inter: ApplicationCommandInteraction[Any]) -> float: """Retrieves the amount of seconds before this application command can be tried again. Parameters @@ -383,7 +383,9 @@ def get_cooldown_retry_after(self, inter: ApplicationCommandInteraction) -> floa return 0.0 # This method isn't really usable in this class, but it's usable in subclasses. - async def invoke(self, inter: ApplicationCommandInteraction, *args: Any, **kwargs: Any) -> None: + async def invoke( + self, inter: ApplicationCommandInteraction[Any], *args: Any, **kwargs: Any + ) -> None: await self.prepare(inter) try: @@ -429,7 +431,7 @@ def has_error_handler(self) -> bool: return hasattr(self, "on_error") async def _call_local_error_handler( - self, inter: ApplicationCommandInteraction, error: CommandError + self, inter: ApplicationCommandInteraction[Any], error: CommandError ) -> Any: if not self.has_error_handler(): return @@ -441,18 +443,18 @@ async def _call_local_error_handler( return await injected(inter, error) async def _call_external_error_handlers( - self, inter: ApplicationCommandInteraction, error: CommandError + self, inter: ApplicationCommandInteraction[Any], error: CommandError ) -> None: """Overridden in subclasses""" raise error async def dispatch_error( - self, inter: ApplicationCommandInteraction, error: CommandError + self, inter: ApplicationCommandInteraction[Any], error: CommandError ) -> None: if not await self._call_local_error_handler(inter, error): await self._call_external_error_handlers(inter, error) - async def call_before_hooks(self, inter: ApplicationCommandInteraction) -> None: + async def call_before_hooks(self, inter: ApplicationCommandInteraction[Any]) -> None: # now that we're done preparing we can call the pre-command hooks # first, call the command local hook: cog = self.cog @@ -487,7 +489,7 @@ async def call_before_hooks(self, inter: ApplicationCommandInteraction) -> None: if hook is not None: await hook(inter) - async def call_after_hooks(self, inter: ApplicationCommandInteraction) -> None: + async def call_after_hooks(self, inter: ApplicationCommandInteraction[Any]) -> None: cog = self.cog if self._after_invoke is not None: instance = getattr(self._after_invoke, "__self__", cog) @@ -568,7 +570,7 @@ def cog_name(self) -> Optional[str]: """Optional[:class:`str`]: The name of the cog this application command belongs to, if any.""" return type(self.cog).__cog_name__ if self.cog is not None else None - async def can_run(self, inter: ApplicationCommandInteraction) -> bool: + async def can_run(self, inter: ApplicationCommandInteraction[Any]) -> bool: """|coro| Checks if the command can be executed by checking all the predicates diff --git a/disnake/ext/commands/bot.py b/disnake/ext/commands/bot.py index 825f96e6ae..47820bdba7 100644 --- a/disnake/ext/commands/bot.py +++ b/disnake/ext/commands/bot.py @@ -6,7 +6,7 @@ import disnake -from .bot_base import BotBase, when_mentioned, when_mentioned_or +from .bot_base import BotBase, CogT, when_mentioned, when_mentioned_or from .interaction_bot_base import InteractionBotBase if TYPE_CHECKING: @@ -42,7 +42,7 @@ MISSING: Any = disnake.utils.MISSING -class Bot(BotBase, InteractionBotBase, disnake.Client): +class Bot(BotBase[CogT], InteractionBotBase[CogT], disnake.Client): """Represents a discord bot. This class is a subclass of :class:`disnake.Client` and as a result @@ -264,7 +264,7 @@ def __init__( ... -class AutoShardedBot(BotBase, InteractionBotBase, disnake.AutoShardedClient): +class AutoShardedBot(BotBase[CogT], InteractionBotBase[CogT], disnake.AutoShardedClient): """Similar to :class:`.Bot`, except that it is inherited from :class:`disnake.AutoShardedClient` instead. """ @@ -316,7 +316,7 @@ def __init__( ... -class InteractionBot(InteractionBotBase, disnake.Client): +class InteractionBot(InteractionBotBase[CogT], disnake.Client): """Represents a discord bot for application commands only. This class is a subclass of :class:`disnake.Client` and as a result @@ -465,7 +465,7 @@ def __init__( ... -class AutoShardedInteractionBot(InteractionBotBase, disnake.AutoShardedClient): +class AutoShardedInteractionBot(InteractionBotBase[CogT], disnake.AutoShardedClient): """Similar to :class:`.InteractionBot`, except that it is inherited from :class:`disnake.AutoShardedClient` instead. """ diff --git a/disnake/ext/commands/bot_base.py b/disnake/ext/commands/bot_base.py index 1bba906c82..4a3baed189 100644 --- a/disnake/ext/commands/bot_base.py +++ b/disnake/ext/commands/bot_base.py @@ -6,7 +6,6 @@ import collections import collections.abc import inspect -import logging import sys import traceback import warnings @@ -15,7 +14,7 @@ import disnake from . import errors -from .common_bot_base import CommonBotBase +from .common_bot_base import CogT, CommonBotBase from .context import Context from .core import GroupMixin from .custom_warnings import MessageContentPrefixWarning @@ -39,14 +38,12 @@ T = TypeVar("T") CFT = TypeVar("CFT", bound="CoroFunc") -CXT = TypeVar("CXT", bound="Context") +CXT = TypeVar("CXT", bound="Context[Any]") PrefixType = Union[str, Iterable[str]] -_log = logging.getLogger(__name__) - -def when_mentioned(bot: BotBase, msg: Message) -> List[str]: +def when_mentioned(bot: BotBase[Any], msg: Message) -> List[str]: """A callable that implements a command prefix equivalent to being mentioned. These are meant to be passed into the :attr:`.Bot.command_prefix` attribute. @@ -55,7 +52,7 @@ def when_mentioned(bot: BotBase, msg: Message) -> List[str]: return [f"<@{bot.user.id}> ", f"<@!{bot.user.id}> "] # type: ignore -def when_mentioned_or(*prefixes: str) -> Callable[[BotBase, Message], List[str]]: +def when_mentioned_or(*prefixes: str) -> Callable[[BotBase[Any], Message], List[str]]: """A callable that implements when mentioned or other prefixes provided. These are meant to be passed into the :attr:`.Bot.command_prefix` attribute. @@ -104,7 +101,7 @@ def __repr__(self) -> str: _default: Any = _DefaultRepr() -class BotBase(CommonBotBase, GroupMixin): +class BotBase(CommonBotBase[CogT], GroupMixin[CogT]): def __init__( self, command_prefix: Optional[ @@ -168,7 +165,11 @@ def __init__( # internal helpers - async def on_command_error(self, context: Context, exception: errors.CommandError) -> None: + async def on_command_error( + self, + context: Context[Self], # pyright: ignore[reportInvalidTypeArguments] + exception: errors.CommandError, + ) -> None: """|coro| The default command error handler provided by the bot. @@ -319,7 +320,7 @@ def whitelist(ctx): self.add_check(func, call_once=True) return func - async def can_run(self, ctx: Context, *, call_once: bool = False) -> bool: + async def can_run(self, ctx: Context[Any], *, call_once: bool = False) -> bool: data = self._check_once if call_once else self._checks if len(data) == 0: @@ -552,7 +553,7 @@ class be provided, it must be similar enough to :class:`.Context`\'s ctx.command = self.all_commands.get(invoker) return ctx - async def invoke(self, ctx: Context) -> None: + async def invoke(self, ctx: Context[Any]) -> None: """|coro| Invokes the command given under the invocation context and @@ -606,5 +607,5 @@ async def process_commands(self, message: Message) -> None: ctx = await self.get_context(message) await self.invoke(ctx) - async def on_message(self, message) -> None: + async def on_message(self, message: Message) -> None: await self.process_commands(message) diff --git a/disnake/ext/commands/cog.py b/disnake/ext/commands/cog.py index 01fd59937c..91bcce818e 100644 --- a/disnake/ext/commands/cog.py +++ b/disnake/ext/commands/cog.py @@ -38,7 +38,10 @@ from .context import Context from .core import Command - AnyBot = Union[Bot, AutoShardedBot, InteractionBot, AutoShardedInteractionBot] + CogT = TypeVar("CogT", bound="Cog") + AnyBot = Union[ + Bot[CogT], AutoShardedBot[CogT], InteractionBot[CogT], AutoShardedInteractionBot[CogT] + ] __all__ = ( @@ -145,7 +148,7 @@ async def bar(self, ctx): __cog_slash_settings__: Dict[str, Any] __cog_user_settings__: Dict[str, Any] __cog_message_settings__: Dict[str, Any] - __cog_commands__: List[Command] + __cog_commands__: List[Command[Any, ..., Any]] __cog_app_commands__: List[InvokableApplicationCommand] __cog_listeners__: List[Tuple[str, str]] @@ -238,7 +241,7 @@ class Cog(metaclass=CogMeta): __cog_name__: ClassVar[str] __cog_settings__: ClassVar[Dict[str, Any]] - __cog_commands__: ClassVar[List[Command]] + __cog_commands__: ClassVar[List[Command[Self, ..., Any]]] __cog_app_commands__: ClassVar[List[InvokableApplicationCommand]] __cog_listeners__: ClassVar[List[Tuple[str, str]]] @@ -285,7 +288,7 @@ def __new__(cls, *args: Any, **kwargs: Any) -> Self: return self - def get_commands(self) -> List[Command]: + def get_commands(self) -> List[Command[Self, ..., Any]]: """Returns a list of commands the cog has. Returns @@ -366,7 +369,7 @@ def description(self) -> str: def description(self, description: str) -> None: self.__cog_description__ = description - def walk_commands(self) -> Generator[Command, None, None]: + def walk_commands(self) -> Generator[Command[Self, ..., Any], None, None]: """An iterator that recursively walks through this cog's commands and subcommands. Yields @@ -491,7 +494,7 @@ def cog_unload(self) -> None: pass @_cog_special_method - def bot_check_once(self, ctx: Context) -> bool: + def bot_check_once(self, ctx: Context[Any]) -> bool: """A special method that registers as a :meth:`.Bot.check_once` check. @@ -503,7 +506,7 @@ def bot_check_once(self, ctx: Context) -> bool: return True @_cog_special_method - def bot_check(self, ctx: Context) -> bool: + def bot_check(self, ctx: Context[Any]) -> bool: """A special method that registers as a :meth:`.Bot.check` check. @@ -515,7 +518,7 @@ def bot_check(self, ctx: Context) -> bool: return True @_cog_special_method - def bot_slash_command_check_once(self, inter: ApplicationCommandInteraction) -> bool: + def bot_slash_command_check_once(self, inter: ApplicationCommandInteraction[Any]) -> bool: """A special method that registers as a :meth:`.Bot.slash_command_check_once` check. @@ -525,7 +528,7 @@ def bot_slash_command_check_once(self, inter: ApplicationCommandInteraction) -> return True @_cog_special_method - def bot_slash_command_check(self, inter: ApplicationCommandInteraction) -> bool: + def bot_slash_command_check(self, inter: ApplicationCommandInteraction[Any]) -> bool: """A special method that registers as a :meth:`.Bot.slash_command_check` check. @@ -535,27 +538,27 @@ def bot_slash_command_check(self, inter: ApplicationCommandInteraction) -> bool: return True @_cog_special_method - def bot_user_command_check_once(self, inter: ApplicationCommandInteraction) -> bool: + def bot_user_command_check_once(self, inter: ApplicationCommandInteraction[Any]) -> bool: """Similar to :meth:`.Bot.slash_command_check_once` but for user commands.""" return True @_cog_special_method - def bot_user_command_check(self, inter: ApplicationCommandInteraction) -> bool: + def bot_user_command_check(self, inter: ApplicationCommandInteraction[Any]) -> bool: """Similar to :meth:`.Bot.slash_command_check` but for user commands.""" return True @_cog_special_method - def bot_message_command_check_once(self, inter: ApplicationCommandInteraction) -> bool: + def bot_message_command_check_once(self, inter: ApplicationCommandInteraction[Any]) -> bool: """Similar to :meth:`.Bot.slash_command_check_once` but for message commands.""" return True @_cog_special_method - def bot_message_command_check(self, inter: ApplicationCommandInteraction) -> bool: + def bot_message_command_check(self, inter: ApplicationCommandInteraction[Any]) -> bool: """Similar to :meth:`.Bot.slash_command_check` but for message commands.""" return True @_cog_special_method - def cog_check(self, ctx: Context) -> bool: + def cog_check(self, ctx: Context[Any]) -> bool: """A special method that registers as a :func:`~.check` for every text command and subcommand in this cog. @@ -567,7 +570,7 @@ def cog_check(self, ctx: Context) -> bool: return True @_cog_special_method - def cog_slash_command_check(self, inter: ApplicationCommandInteraction) -> bool: + def cog_slash_command_check(self, inter: ApplicationCommandInteraction[Any]) -> bool: """A special method that registers as a :func:`~.check` for every slash command and subcommand in this cog. @@ -577,17 +580,17 @@ def cog_slash_command_check(self, inter: ApplicationCommandInteraction) -> bool: return True @_cog_special_method - def cog_user_command_check(self, inter: ApplicationCommandInteraction) -> bool: + def cog_user_command_check(self, inter: ApplicationCommandInteraction[Any]) -> bool: """Similar to :meth:`.Cog.cog_slash_command_check` but for user commands.""" return True @_cog_special_method - def cog_message_command_check(self, inter: ApplicationCommandInteraction) -> bool: + def cog_message_command_check(self, inter: ApplicationCommandInteraction[Any]) -> bool: """Similar to :meth:`.Cog.cog_slash_command_check` but for message commands.""" return True @_cog_special_method - async def cog_command_error(self, ctx: Context, error: Exception) -> None: + async def cog_command_error(self, ctx: Context[Any], error: Exception) -> None: """A special method that is called whenever an error is dispatched inside this cog. @@ -609,7 +612,7 @@ async def cog_command_error(self, ctx: Context, error: Exception) -> None: @_cog_special_method async def cog_slash_command_error( - self, inter: ApplicationCommandInteraction, error: Exception + self, inter: ApplicationCommandInteraction[Any], error: Exception ) -> None: """A special method that is called whenever an error is dispatched inside this cog. @@ -630,20 +633,20 @@ async def cog_slash_command_error( @_cog_special_method async def cog_user_command_error( - self, inter: ApplicationCommandInteraction, error: Exception + self, inter: ApplicationCommandInteraction[Any], error: Exception ) -> None: """Similar to :func:`cog_slash_command_error` but for user commands.""" pass @_cog_special_method async def cog_message_command_error( - self, inter: ApplicationCommandInteraction, error: Exception + self, inter: ApplicationCommandInteraction[Any], error: Exception ) -> None: """Similar to :func:`cog_slash_command_error` but for message commands.""" pass @_cog_special_method - async def cog_before_invoke(self, ctx: Context) -> None: + async def cog_before_invoke(self, ctx: Context[Any]) -> None: """A special method that acts as a cog local pre-invoke hook, similar to :meth:`.Command.before_invoke`. @@ -659,7 +662,7 @@ async def cog_before_invoke(self, ctx: Context) -> None: pass @_cog_special_method - async def cog_after_invoke(self, ctx: Context) -> None: + async def cog_after_invoke(self, ctx: Context[Any]) -> None: """A special method that acts as a cog local post-invoke hook, similar to :meth:`.Command.after_invoke`. @@ -675,7 +678,9 @@ async def cog_after_invoke(self, ctx: Context) -> None: pass @_cog_special_method - async def cog_before_slash_command_invoke(self, inter: ApplicationCommandInteraction) -> None: + async def cog_before_slash_command_invoke( + self, inter: ApplicationCommandInteraction[Any] + ) -> None: """A special method that acts as a cog local pre-invoke hook. This is similar to :meth:`.Command.before_invoke` but for slash commands. @@ -690,7 +695,9 @@ async def cog_before_slash_command_invoke(self, inter: ApplicationCommandInterac pass @_cog_special_method - async def cog_after_slash_command_invoke(self, inter: ApplicationCommandInteraction) -> None: + async def cog_after_slash_command_invoke( + self, inter: ApplicationCommandInteraction[Any] + ) -> None: """A special method that acts as a cog local post-invoke hook. This is similar to :meth:`.Command.after_invoke` but for slash commands. @@ -705,26 +712,34 @@ async def cog_after_slash_command_invoke(self, inter: ApplicationCommandInteract pass @_cog_special_method - async def cog_before_user_command_invoke(self, inter: ApplicationCommandInteraction) -> None: + async def cog_before_user_command_invoke( + self, inter: ApplicationCommandInteraction[Any] + ) -> None: """Similar to :meth:`cog_before_slash_command_invoke` but for user commands.""" pass @_cog_special_method - async def cog_after_user_command_invoke(self, inter: ApplicationCommandInteraction) -> None: + async def cog_after_user_command_invoke( + self, inter: ApplicationCommandInteraction[Any] + ) -> None: """Similar to :meth:`cog_after_slash_command_invoke` but for user commands.""" pass @_cog_special_method - async def cog_before_message_command_invoke(self, inter: ApplicationCommandInteraction) -> None: + async def cog_before_message_command_invoke( + self, inter: ApplicationCommandInteraction[Any] + ) -> None: """Similar to :meth:`cog_before_slash_command_invoke` but for message commands.""" pass @_cog_special_method - async def cog_after_message_command_invoke(self, inter: ApplicationCommandInteraction) -> None: + async def cog_after_message_command_invoke( + self, inter: ApplicationCommandInteraction[Any] + ) -> None: """Similar to :meth:`cog_after_slash_command_invoke` but for message commands.""" pass - def _inject(self, bot: AnyBot) -> Self: + def _inject(self, bot: AnyBot[Self]) -> Self: from .bot import AutoShardedInteractionBot, InteractionBot cls = self.__class__ @@ -832,7 +847,7 @@ def _inject(self, bot: AnyBot) -> Self: return self - def _eject(self, bot: AnyBot) -> None: + def _eject(self, bot: AnyBot[Self]) -> None: cls = self.__class__ try: diff --git a/disnake/ext/commands/common_bot_base.py b/disnake/ext/commands/common_bot_base.py index 8658aa369a..38b2da8566 100644 --- a/disnake/ext/commands/common_bot_base.py +++ b/disnake/ext/commands/common_bot_base.py @@ -21,11 +21,8 @@ if TYPE_CHECKING: from ._types import CoroFunc - from .bot import AutoShardedBot, AutoShardedInteractionBot, Bot, InteractionBot from .help import HelpCommand - AnyBot = Union[Bot, AutoShardedBot, InteractionBot, AutoShardedInteractionBot] - __all__ = ("CommonBotBase",) _log = logging.getLogger(__name__) diff --git a/disnake/ext/commands/context.py b/disnake/ext/commands/context.py index 0876e7d3a4..0810822228 100644 --- a/disnake/ext/commands/context.py +++ b/disnake/ext/commands/context.py @@ -32,7 +32,7 @@ T = TypeVar("T") -BotT = TypeVar("BotT", bound="Union[Bot, AutoShardedBot]") +BotT = TypeVar("BotT", bound="Union[Bot[Any], AutoShardedBot[Any]]") CogT = TypeVar("CogT", bound="Cog") if TYPE_CHECKING: @@ -106,10 +106,10 @@ def __init__( args: List[Any] = MISSING, kwargs: Dict[str, Any] = MISSING, prefix: Optional[str] = None, - command: Optional[Command] = None, + command: Optional[Command[Any, ..., Any]] = None, invoked_with: Optional[str] = None, invoked_parents: List[str] = MISSING, - invoked_subcommand: Optional[Command] = None, + invoked_subcommand: Optional[Command[Any, ..., Any]] = None, subcommand_passed: Optional[str] = None, command_failed: bool = False, current_parameter: Optional[inspect.Parameter] = None, @@ -119,11 +119,11 @@ def __init__( self.args: List[Any] = args or [] self.kwargs: Dict[str, Any] = kwargs or {} self.prefix: Optional[str] = prefix - self.command: Optional[Command] = command + self.command: Optional[Command[Any, ..., Any]] = command self.view: StringView = view self.invoked_with: Optional[str] = invoked_with self.invoked_parents: List[str] = invoked_parents or [] - self.invoked_subcommand: Optional[Command] = invoked_subcommand + self.invoked_subcommand: Optional[Command[Any, ..., Any]] = invoked_subcommand self.subcommand_passed: Optional[str] = subcommand_passed self.command_failed: bool = command_failed self.current_parameter: Optional[inspect.Parameter] = current_parameter @@ -371,7 +371,7 @@ async def reply(self, content: Optional[str] = None, **kwargs: Any) -> Message: return await self.message.reply(content, **kwargs) -class GuildContext(Context): +class GuildContext(Context[BotT]): """A Context subclass meant for annotation No runtime behavior is changed but annotations are modified @@ -384,4 +384,4 @@ class GuildContext(Context): me: Member -AnyContext = Union[Context, ApplicationCommandInteraction] +AnyContext = Union[Context[BotT], ApplicationCommandInteraction[BotT]] diff --git a/disnake/ext/commands/converter.py b/disnake/ext/commands/converter.py index 422416fd33..24287a0e2d 100644 --- a/disnake/ext/commands/converter.py +++ b/disnake/ext/commands/converter.py @@ -1218,7 +1218,7 @@ def is_generic_type(tp: Any, *, _GenericAlias: Type = _GenericAlias) -> bool: async def _actual_conversion( - ctx: Context, + ctx: Context[Any], converter: Union[Type[T], Type[Converter[T]], Converter[T], Callable[[str], T]], argument: str, param: inspect.Parameter, @@ -1257,7 +1257,7 @@ async def _actual_conversion( raise BadArgument(f'Converting to "{name}" failed for parameter "{param.name}".') from exc -async def run_converters(ctx: Context, converter, argument: str, param: inspect.Parameter): +async def run_converters(ctx: Context[Any], converter, argument: str, param: inspect.Parameter): """|coro| Runs converters for a given converter, argument, and parameter. diff --git a/disnake/ext/commands/core.py b/disnake/ext/commands/core.py index b9d49ab269..b7af3a3d3a 100644 --- a/disnake/ext/commands/core.py +++ b/disnake/ext/commands/core.py @@ -102,6 +102,8 @@ MISSING: Any = disnake.utils.MISSING T = TypeVar("T") +KT = TypeVar("KT") +VT = TypeVar("VT") CogT = TypeVar("CogT", bound="Optional[Cog]") CommandT = TypeVar("CommandT", bound="Command") ContextT = TypeVar("ContextT", bound="Context") @@ -121,15 +123,16 @@ P = TypeVar("P") -def wrap_callback(coro): +def wrap_callback(coro: Callable[..., Coro[T]]) -> Callable[..., Coro[T | None]]: + # there's no way to type it nicely without causing issues down the line @functools.wraps(coro) - async def wrapped(*args, **kwargs): + async def wrapped(*args: Any, **kwargs: Any): try: ret = await coro(*args, **kwargs) except CommandError: raise except asyncio.CancelledError: - return + return None except Exception as exc: raise CommandInvokeError(exc) from exc return ret @@ -137,9 +140,12 @@ async def wrapped(*args, **kwargs): return wrapped -def hooked_wrapped_callback(command, ctx, coro): +def hooked_wrapped_callback( + command: "Command[Any, ..., T]", ctx: Context[Any], coro: Callable[..., Coro[T]] +) -> Callable[..., Coro[T | None]]: + # there's no way to type it nicely without causing issues down the line @functools.wraps(coro) - async def wrapped(*args, **kwargs): + async def wrapped(*args: Any, **kwargs: Any) -> T | None: try: ret = await coro(*args, **kwargs) except CommandError: @@ -147,7 +153,7 @@ async def wrapped(*args, **kwargs): raise except asyncio.CancelledError: ctx.command_failed = True - return + return None except Exception as exc: ctx.command_failed = True raise CommandInvokeError(exc) from exc @@ -161,23 +167,23 @@ async def wrapped(*args, **kwargs): return wrapped -class _CaseInsensitiveDict(dict): - def __contains__(self, k) -> bool: +class _CaseInsensitiveDict(Dict[str, VT]): + def __contains__(self, k: str) -> bool: return super().__contains__(k.casefold()) - def __delitem__(self, k): + def __delitem__(self, k: str): return super().__delitem__(k.casefold()) - def __getitem__(self, k): + def __getitem__(self, k: str): return super().__getitem__(k.casefold()) - def get(self, k, default=None): + def get(self, k: str, default: T = None) -> Union[VT, T]: return super().get(k.casefold(), default) - def pop(self, k, default=None): + def pop(self, k: str, default: T = None) -> Union[VT, T]: return super().pop(k.casefold(), default) - def __setitem__(self, k, v) -> None: + def __setitem__(self, k: str, v: VT) -> None: super().__setitem__(k.casefold(), v) @@ -428,7 +434,7 @@ def update(self, **kwargs: Any) -> None: """ self.__init__(self.callback, **dict(self.__original_kwargs__, **kwargs)) - async def __call__(self, context: Context, *args: P.args, **kwargs: P.kwargs) -> T: + async def __call__(self, context: Context[Any], *args: P.args, **kwargs: P.kwargs) -> T: """|coro| Calls the internal callback that the command holds. @@ -483,7 +489,7 @@ def _update_copy(self: CommandT, kwargs: Dict[str, Any]) -> CommandT: else: return self.copy() - async def dispatch_error(self, ctx: Context, error: Exception) -> None: + async def dispatch_error(self, ctx: Context[Any], error: CommandError) -> None: stop_propagation = False ctx.command_failed = True cog = self.cog @@ -512,7 +518,7 @@ async def dispatch_error(self, ctx: Context, error: Exception) -> None: return # noqa: B012 ctx.bot.dispatch("command_error", ctx, error) - async def transform(self, ctx: Context, param: inspect.Parameter) -> Any: + async def transform(self, ctx: Context[Any], param: inspect.Parameter) -> Any: required = param.default is param.empty converter = get_converter(param) consume_rest_is_special = param.kind == param.KEYWORD_ONLY and not self.rest_is_raw @@ -564,7 +570,7 @@ async def transform(self, ctx: Context, param: inspect.Parameter) -> Any: return await run_converters(ctx, converter, argument, param) # type: ignore async def _transform_greedy_pos( - self, ctx: Context, param: inspect.Parameter, required: bool, converter: Any + self, ctx: Context[Any], param: inspect.Parameter, required: bool, converter: Any ) -> Any: view = ctx.view result = [] @@ -587,7 +593,7 @@ async def _transform_greedy_pos( return result async def _transform_greedy_var_pos( - self, ctx: Context, param: inspect.Parameter, converter: Any + self, ctx: Context[Any], param: inspect.Parameter, converter: Any ) -> Any: view = ctx.view previous = view.index @@ -617,7 +623,7 @@ def full_parent_name(self) -> str: in ``?one two three`` the parent name would be ``one two``. """ entries = [] - command: Command[Any, ..., Any] = self + command: Command[CogT, ..., Any] = self # command.parent is type-hinted as GroupMixin some attributes are resolved via MRO while command.parent is not None: command = command.parent # type: ignore @@ -626,7 +632,7 @@ def full_parent_name(self) -> str: return " ".join(reversed(entries)) @property - def parents(self) -> List[Group]: + def parents(self) -> List[Group[CogT, ..., Any]]: """List[:class:`Group`]: Retrieves the parents of this command. If the command has no parents then it returns an empty :class:`list`. @@ -636,7 +642,7 @@ def parents(self) -> List[Group]: .. versionadded:: 1.1 """ entries = [] - command: Command[Any, ..., Any] = self + command: Command[CogT, ..., Any] = self while command.parent is not None: command = command.parent # type: ignore entries.append(command) @@ -644,7 +650,7 @@ def parents(self) -> List[Group]: return entries @property - def root_parent(self) -> Optional[Group]: + def root_parent(self) -> Optional[Group[CogT, ..., Any]]: """Optional[:class:`Group`]: Retrieves the root parent of this command. If the command has no parents then it returns ``None``. @@ -672,7 +678,7 @@ def qualified_name(self) -> str: def __str__(self) -> str: return self.qualified_name - async def _parse_arguments(self, ctx: Context) -> None: + async def _parse_arguments(self, ctx: Context[Any]) -> None: ctx.args = [ctx] if self.cog is None else [self.cog, ctx] ctx.kwargs = {} args = ctx.args @@ -706,7 +712,7 @@ async def _parse_arguments(self, ctx: Context) -> None: if not self.ignore_extra and not view.eof: raise TooManyArguments(f"Too many arguments passed to {self.qualified_name}") - async def call_before_hooks(self, ctx: Context) -> None: + async def call_before_hooks(self, ctx: Context[Any]) -> None: # now that we're done preparing we can call the pre-command hooks # first, call the command local hook: cog = self.cog @@ -731,7 +737,7 @@ async def call_before_hooks(self, ctx: Context) -> None: if hook is not None: await hook(ctx) - async def call_after_hooks(self, ctx: Context) -> None: + async def call_after_hooks(self, ctx: Context[Any]) -> None: cog = self.cog if self._after_invoke is not None: instance = getattr(self._after_invoke, "__self__", cog) @@ -750,7 +756,7 @@ async def call_after_hooks(self, ctx: Context) -> None: if hook is not None: await hook(ctx) - def _prepare_cooldowns(self, ctx: Context) -> None: + def _prepare_cooldowns(self, ctx: Context[Any]) -> None: if self._buckets.valid: dt = ctx.message.edited_at or ctx.message.created_at current = dt.replace(tzinfo=datetime.timezone.utc).timestamp() @@ -760,7 +766,7 @@ def _prepare_cooldowns(self, ctx: Context) -> None: if retry_after: raise CommandOnCooldown(bucket, retry_after, self._buckets.type) # type: ignore - async def prepare(self, ctx: Context) -> None: + async def prepare(self, ctx: Context[Any]) -> None: ctx.command = self if not await self.can_run(ctx): @@ -784,7 +790,7 @@ async def prepare(self, ctx: Context) -> None: await self._max_concurrency.release(ctx) # type: ignore raise - def is_on_cooldown(self, ctx: Context) -> bool: + def is_on_cooldown(self, ctx: Context[Any]) -> bool: """Checks whether the command is currently on cooldown. Parameters @@ -805,7 +811,7 @@ def is_on_cooldown(self, ctx: Context) -> bool: current = dt.replace(tzinfo=datetime.timezone.utc).timestamp() return bucket.get_tokens(current) == 0 - def reset_cooldown(self, ctx: Context) -> None: + def reset_cooldown(self, ctx: Context[Any]) -> None: """Resets the cooldown on this command. Parameters @@ -817,7 +823,7 @@ def reset_cooldown(self, ctx: Context) -> None: bucket = self._buckets.get_bucket(ctx.message) bucket.reset() - def get_cooldown_retry_after(self, ctx: Context) -> float: + def get_cooldown_retry_after(self, ctx: Context[Any]) -> float: """Retrieves the amount of seconds before this command can be tried again. .. versionadded:: 1.4 @@ -841,7 +847,7 @@ def get_cooldown_retry_after(self, ctx: Context) -> float: return 0.0 - async def invoke(self, ctx: Context) -> None: + async def invoke(self, ctx: Context[Any]) -> None: await self.prepare(ctx) # terminate the invoked_subcommand chain. @@ -852,7 +858,7 @@ async def invoke(self, ctx: Context) -> None: injected = hooked_wrapped_callback(self, ctx, self.callback) await injected(*ctx.args, **ctx.kwargs) - async def reinvoke(self, ctx: Context, *, call_hooks: bool = False) -> None: + async def reinvoke(self, ctx: Context[Any], *, call_hooks: bool = False) -> None: ctx.command = self await self._parse_arguments(ctx) @@ -1038,7 +1044,7 @@ def signature(self) -> str: return " ".join(result) - async def can_run(self, ctx: Context) -> bool: + async def can_run(self, ctx: Context[Any]) -> bool: """|coro| Checks if the command can be executed by checking all the predicates @@ -1403,7 +1409,7 @@ def copy(self: GroupT) -> GroupT: ret.add_command(cmd.copy()) return ret - async def invoke(self, ctx: Context) -> None: + async def invoke(self, ctx: Context[Any]) -> None: ctx.invoked_subcommand = None ctx.subcommand_passed = None early_invoke = not self.invoke_without_command @@ -1434,7 +1440,7 @@ async def invoke(self, ctx: Context) -> None: view.previous = previous await super().invoke(ctx) - async def reinvoke(self, ctx: Context, *, call_hooks: bool = False) -> None: + async def reinvoke(self, ctx: Context[Any], *, call_hooks: bool = False) -> None: ctx.invoked_subcommand = None early_invoke = not self.invoke_without_command if early_invoke: @@ -1703,7 +1709,9 @@ async def only_me(ctx): The predicate to check if the command should be invoked. """ - def decorator(func: Union[Command, CoroFunc]) -> Union[Command, CoroFunc]: + def decorator( + func: Union[Command[CogT, P, T], CoroFunc], + ) -> Union[Command[CogT, P, T], CoroFunc]: if hasattr(func, "__command_flag__"): func.checks.append(predicate) else: @@ -2525,7 +2533,9 @@ def cooldown( Callables are now supported for custom bucket types. """ - def decorator(func: Union[Command, CoroFunc]) -> Union[Command, CoroFunc]: + def decorator( + func: Union[Command[CogT, P, T], CoroFunc], + ) -> Union[Command[CogT, P, T], CoroFunc]: if hasattr(func, "__command_flag__"): func._buckets = CooldownMapping(Cooldown(rate, per), type) else: @@ -2569,7 +2579,9 @@ def dynamic_cooldown( if not callable(cooldown): raise TypeError("A callable must be provided") - def decorator(func: Union[Command, CoroFunc]) -> Union[Command, CoroFunc]: + def decorator( + func: Union[Command[CogT, P, T], CoroFunc], + ) -> Union[Command[CogT, P, T], CoroFunc]: if hasattr(func, "__command_flag__"): func._buckets = DynamicCooldownMapping(cooldown, type) else: @@ -2605,7 +2617,9 @@ def max_concurrency( then the command waits until it can be executed. """ - def decorator(func: Union[Command, CoroFunc]) -> Union[Command, CoroFunc]: + def decorator( + func: Union[Command[CogT, P, T], CoroFunc], + ) -> Union[Command[CogT, P, T], CoroFunc]: value = MaxConcurrency(number, per=per, wait=wait) if hasattr(func, "__command_flag__"): func._max_concurrency = value @@ -2654,7 +2668,9 @@ async def why(self, ctx): # Output: bot.add_cog(What()) """ - def decorator(func: Union[Command, CoroFunc]) -> Union[Command, CoroFunc]: + def decorator( + func: Union[Command[CogT, P, T], CoroFunc], + ) -> Union[Command[CogT, P, T], CoroFunc]: if hasattr(func, "__command_flag__"): func.before_invoke(coro) else: @@ -2673,7 +2689,9 @@ def after_invoke(coro) -> Callable[[T], T]: .. versionadded:: 1.4 """ - def decorator(func: Union[Command, CoroFunc]) -> Union[Command, CoroFunc]: + def decorator( + func: Union[Command[CogT, P, T], CoroFunc], + ) -> Union[Command[CogT, P, T], CoroFunc]: if hasattr(func, "__command_flag__"): func.after_invoke(coro) else: diff --git a/disnake/ext/commands/ctx_menus_core.py b/disnake/ext/commands/ctx_menus_core.py index 0e84b5a89d..1f6e96829c 100644 --- a/disnake/ext/commands/ctx_menus_core.py +++ b/disnake/ext/commands/ctx_menus_core.py @@ -70,7 +70,7 @@ class InvokableUserCommand(InvokableApplicationCommand): def __init__( self, - func: InteractionCommandCallback[CogT, UserCommandInteraction, P], + func: InteractionCommandCallback[CogT, UserCommandInteraction[Any], P], *, name: LocalizedOptional = None, dm_permission: Optional[bool] = None, @@ -106,7 +106,7 @@ def __init__( ) async def _call_external_error_handlers( - self, inter: ApplicationCommandInteraction, error: CommandError + self, inter: ApplicationCommandInteraction[Any], error: CommandError ) -> None: stop_propagation = False cog = self.cog @@ -123,7 +123,7 @@ async def _call_external_error_handlers( async def __call__( self, - interaction: ApplicationCommandInteraction, + interaction: ApplicationCommandInteraction[Any], target: Any = None, *args: Any, **kwargs: Any, @@ -176,7 +176,7 @@ class InvokableMessageCommand(InvokableApplicationCommand): def __init__( self, - func: InteractionCommandCallback[CogT, MessageCommandInteraction, P], + func: InteractionCommandCallback[CogT, MessageCommandInteraction[Any], P], *, name: LocalizedOptional = None, dm_permission: Optional[bool] = None, @@ -206,7 +206,7 @@ def __init__( ) async def _call_external_error_handlers( - self, inter: ApplicationCommandInteraction, error: CommandError + self, inter: ApplicationCommandInteraction[Any], error: CommandError ) -> None: stop_propagation = False cog = self.cog @@ -223,7 +223,7 @@ async def _call_external_error_handlers( async def __call__( self, - interaction: ApplicationCommandInteraction, + interaction: ApplicationCommandInteraction[Any], target: Any = None, *args: Any, **kwargs: Any, @@ -246,7 +246,9 @@ def user_command( auto_sync: Optional[bool] = None, extras: Optional[Dict[str, Any]] = None, **kwargs: Any, -) -> Callable[[InteractionCommandCallback[CogT, UserCommandInteraction, P]], InvokableUserCommand]: +) -> Callable[ + [InteractionCommandCallback[CogT, UserCommandInteraction[Any], P]], InvokableUserCommand +]: """A shortcut decorator that builds a user command. Parameters @@ -292,7 +294,7 @@ def user_command( """ def decorator( - func: InteractionCommandCallback[CogT, UserCommandInteraction, P] + func: InteractionCommandCallback[CogT, UserCommandInteraction[Any], P] ) -> InvokableUserCommand: if not asyncio.iscoroutinefunction(func): raise TypeError(f"<{func.__qualname__}> must be a coroutine function") @@ -326,7 +328,7 @@ def message_command( extras: Optional[Dict[str, Any]] = None, **kwargs: Any, ) -> Callable[ - [InteractionCommandCallback[CogT, MessageCommandInteraction, P]], + [InteractionCommandCallback[CogT, MessageCommandInteraction[Any], P]], InvokableMessageCommand, ]: """A shortcut decorator that builds a message command. @@ -374,7 +376,7 @@ def message_command( """ def decorator( - func: InteractionCommandCallback[CogT, MessageCommandInteraction, P] + func: InteractionCommandCallback[CogT, MessageCommandInteraction[Any], P] ) -> InvokableMessageCommand: if not asyncio.iscoroutinefunction(func): raise TypeError(f"<{func.__qualname__}> must be a coroutine function") diff --git a/disnake/ext/commands/errors.py b/disnake/ext/commands/errors.py index cfa4c12f03..1855eecf1b 100644 --- a/disnake/ext/commands/errors.py +++ b/disnake/ext/commands/errors.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Any, Callable, List, Optional, Tuple, Type, Union +from typing import TYPE_CHECKING, Any, Callable, List, Optional, Tuple, Union from disnake.errors import ClientException, DiscordException from disnake.utils import humanize_list @@ -802,10 +802,10 @@ class BadUnionArgument(UserInputError): """ def __init__( - self, param: Parameter, converters: Tuple[Type, ...], errors: List[CommandError] + self, param: Parameter, converters: Tuple[type, ...], errors: List[CommandError] ) -> None: self.param: Parameter = param - self.converters: Tuple[Type, ...] = converters + self.converters: Tuple[type, ...] = converters self.errors: List[CommandError] = errors def _get_name(x): diff --git a/disnake/ext/commands/flag_converter.py b/disnake/ext/commands/flag_converter.py index 37c97936c0..aae79c5dd2 100644 --- a/disnake/ext/commands/flag_converter.py +++ b/disnake/ext/commands/flag_converter.py @@ -341,7 +341,7 @@ def __new__( async def tuple_convert_all( - ctx: Context, argument: str, flag: Flag, converter: Any + ctx: Context[Any], argument: str, flag: Flag, converter: Any ) -> Tuple[Any, ...]: view = StringView(argument) results = [] @@ -368,7 +368,7 @@ async def tuple_convert_all( async def tuple_convert_flag( - ctx: Context, argument: str, flag: Flag, converters: Any + ctx: Context[Any], argument: str, flag: Flag, converters: Any ) -> Tuple[Any, ...]: view = StringView(argument) results = [] @@ -397,7 +397,7 @@ async def tuple_convert_flag( return tuple(results) -async def convert_flag(ctx: Context, argument: str, flag: Flag, annotation: Any = None) -> Any: +async def convert_flag(ctx: Context[Any], argument: str, flag: Flag, annotation: Any = None) -> Any: param: inspect.Parameter = ctx.current_parameter # type: ignore annotation = annotation or flag.annotation if origin := get_origin(annotation): @@ -473,7 +473,7 @@ def __iter__(self) -> Iterator[Tuple[str, Any]]: yield (flag.name, getattr(self, flag.attribute)) @classmethod - async def _construct_default(cls, ctx: Context) -> Self: + async def _construct_default(cls, ctx: Context[Any]) -> Self: self = cls.__new__(cls) flags = cls.__commands_flags__ for flag in flags.values(): @@ -544,7 +544,7 @@ def parse_flags(cls, argument: str) -> Dict[str, List[str]]: return result @classmethod - async def convert(cls, ctx: Context, argument: str) -> Self: + async def convert(cls, ctx: Context[Any], argument: str) -> Self: """|coro| The method that actually converters an argument to the flag mapping. diff --git a/disnake/ext/commands/help.py b/disnake/ext/commands/help.py index ecd3988b86..e62f418152 100644 --- a/disnake/ext/commands/help.py +++ b/disnake/ext/commands/help.py @@ -300,7 +300,7 @@ def __init__(self, **options) -> None: self.command_attrs = attrs = options.pop("command_attrs", {}) attrs.setdefault("name", "help") attrs.setdefault("help", "Shows this message") - self.context: Context = disnake.utils.MISSING + self.context: Context[Any] = disnake.utils.MISSING self._command_impl = _HelpCommandImpl(self, **self.command_attrs) def copy(self): diff --git a/disnake/ext/commands/interaction_bot_base.py b/disnake/ext/commands/interaction_bot_base.py index 110066b679..ab63af9ef3 100644 --- a/disnake/ext/commands/interaction_bot_base.py +++ b/disnake/ext/commands/interaction_bot_base.py @@ -31,7 +31,7 @@ from disnake.utils import warn_deprecated from . import errors -from .base_core import InvokableApplicationCommand +from .base_core import CogT, InvokableApplicationCommand from .common_bot_base import CommonBotBase from .ctx_menus_core import ( InvokableMessageCommand, @@ -55,7 +55,7 @@ from disnake.permissions import Permissions from ._types import AppCheck, CoroFunc - from .base_core import CogT, CommandCallback, InteractionCommandCallback + from .base_core import CommandCallback, InteractionCommandCallback P = ParamSpec("P") @@ -139,7 +139,7 @@ def _format_diff(diff: _Diff) -> str: return "\n".join(f"| {line}" for line in lines) -class InteractionBotBase(CommonBotBase): +class InteractionBotBase(CommonBotBase[CogT]): def __init__( self, *, @@ -587,7 +587,7 @@ def user_command( extras: Optional[Dict[str, Any]] = None, **kwargs: Any, ) -> Callable[ - [InteractionCommandCallback[CogT, UserCommandInteraction, P]], InvokableUserCommand + [InteractionCommandCallback[CogT, UserCommandInteraction[Any], P]], InvokableUserCommand ]: """A shortcut decorator that invokes :func:`~disnake.ext.commands.user_command` and adds it to the internal command list. @@ -635,7 +635,7 @@ def user_command( """ def decorator( - func: InteractionCommandCallback[CogT, UserCommandInteraction, P] + func: InteractionCommandCallback[CogT, UserCommandInteraction[Any], P], ) -> InvokableUserCommand: result = user_command( name=name, @@ -664,7 +664,8 @@ def message_command( extras: Optional[Dict[str, Any]] = None, **kwargs: Any, ) -> Callable[ - [InteractionCommandCallback[CogT, MessageCommandInteraction, P]], InvokableMessageCommand + [InteractionCommandCallback[CogT, MessageCommandInteraction[Any], P]], + InvokableMessageCommand, ]: """A shortcut decorator that invokes :func:`~disnake.ext.commands.message_command` and adds it to the internal command list. @@ -712,7 +713,7 @@ def message_command( """ def decorator( - func: InteractionCommandCallback[CogT, MessageCommandInteraction, P] + func: InteractionCommandCallback[CogT, MessageCommandInteraction[Any], P], ) -> InvokableMessageCommand: result = message_command( name=name, @@ -920,7 +921,7 @@ def _schedule_delayed_command_sync(self) -> None: # Error handlers async def on_slash_command_error( - self, interaction: ApplicationCommandInteraction, exception: errors.CommandError + self, interaction: ApplicationCommandInteraction[Any], exception: errors.CommandError ) -> None: """|coro| @@ -948,7 +949,7 @@ async def on_slash_command_error( ) async def on_user_command_error( - self, interaction: ApplicationCommandInteraction, exception: errors.CommandError + self, interaction: ApplicationCommandInteraction[Any], exception: errors.CommandError ) -> None: """|coro| @@ -968,7 +969,7 @@ async def on_user_command_error( ) async def on_message_command_error( - self, interaction: ApplicationCommandInteraction, exception: errors.CommandError + self, interaction: ApplicationCommandInteraction[Any], exception: errors.CommandError ) -> None: """|coro| @@ -1132,8 +1133,8 @@ def application_command_check( user_commands: bool = False, message_commands: bool = False, ) -> Callable[ - [Callable[[ApplicationCommandInteraction], Any]], - Callable[[ApplicationCommandInteraction], Any], + [Callable[[ApplicationCommandInteraction[Any]], Any]], + Callable[[ApplicationCommandInteraction[Any]], Any], ]: """A decorator that adds a global application command check to the bot. @@ -1175,8 +1176,8 @@ def check_app_commands(inter): message_commands = True def decorator( - func: Callable[[ApplicationCommandInteraction], Any] - ) -> Callable[[ApplicationCommandInteraction], Any]: + func: Callable[[ApplicationCommandInteraction[Any]], Any], + ) -> Callable[[ApplicationCommandInteraction[Any]], Any]: # T was used instead of Check to ensure the type matches on return self.add_app_command_check( func, @@ -1190,7 +1191,7 @@ def decorator( return decorator async def application_command_can_run( - self, inter: ApplicationCommandInteraction, *, call_once: bool = False + self, inter: ApplicationCommandInteraction[Any], *, call_once: bool = False ) -> bool: if inter.data.type is ApplicationCommandType.chat_input: checks = self._slash_command_check_once if call_once else self._slash_command_checks @@ -1264,7 +1265,7 @@ def after_message_command_invoke(self, coro: CFT) -> CFT: # command processing async def process_app_command_autocompletion( - self, inter: ApplicationCommandInteraction + self, inter: ApplicationCommandInteraction[Any] ) -> None: """|coro| @@ -1290,7 +1291,7 @@ async def process_app_command_autocompletion( await slash_command._call_relevant_autocompleter(inter) async def process_application_commands( - self, interaction: ApplicationCommandInteraction + self, interaction: ApplicationCommandInteraction[Any] ) -> None: """|coro| @@ -1382,10 +1383,10 @@ async def process_application_commands( except errors.CommandError as exc: await app_command.dispatch_error(interaction, exc) - async def on_application_command(self, interaction: ApplicationCommandInteraction) -> None: + async def on_application_command(self, interaction: ApplicationCommandInteraction[Any]) -> None: await self.process_application_commands(interaction) async def on_application_command_autocomplete( - self, interaction: ApplicationCommandInteraction + self, interaction: ApplicationCommandInteraction[Any] ) -> None: await self.process_app_command_autocompletion(interaction) diff --git a/disnake/ext/commands/params.py b/disnake/ext/commands/params.py index e472c1ae13..b448605ca4 100644 --- a/disnake/ext/commands/params.py +++ b/disnake/ext/commands/params.py @@ -497,7 +497,7 @@ class ParamInfo: disnake.Attachment: OptionType.attachment.value, # fmt: on } - _registered_converters: ClassVar[Dict[type, Callable]] = {} + _registered_converters: ClassVar[Dict[type, Callable[..., Any]]] = {} def __init__( self, @@ -766,7 +766,9 @@ def parse_annotation(self, annotation: Any, converter_mode: bool = False) -> boo return True - def parse_converter_annotation(self, converter: Callable, fallback_annotation: Any) -> None: + def parse_converter_annotation( + self, converter: Callable[..., Any], fallback_annotation: Any + ) -> None: if isinstance(converter, (types.FunctionType, types.MethodType)): converter_func = converter else: @@ -882,7 +884,7 @@ def safe_call(function: Callable[..., T], /, *possible_args: Any, **possible_kwa def isolate_self( - function: Callable, + function: Callable[..., Any], parameters: Optional[Dict[str, inspect.Parameter]] = None, ) -> Tuple[Tuple[Optional[inspect.Parameter], ...], Dict[str, inspect.Parameter]]: """Create parameters without self and the first interaction. @@ -946,7 +948,7 @@ def classify_autocompleter(autocompleter: AnyAutocompleter) -> None: def collect_params( - function: Callable, + function: Callable[..., Any], parameters: Optional[Dict[str, inspect.Parameter]] = None, ) -> Tuple[Optional[str], Optional[str], List[ParamInfo], Dict[str, Injection]]: """Collect all parameters in a function. @@ -999,7 +1001,7 @@ def collect_params( ) -def collect_nested_params(function: Callable) -> List[ParamInfo]: +def collect_nested_params(function: Callable[..., Any]) -> List[ParamInfo]: """Collect all options from a function""" # TODO: Have these be actually sorted properly and not have injections always at the end _, _, paraminfos, injections = collect_params(function) @@ -1055,8 +1057,12 @@ async def _helper(name: str, injection: Injection) -> Tuple[str, Any]: async def call_param_func( - function: Callable, interaction: ApplicationCommandInteraction, /, *args: Any, **kwargs: Any -) -> Any: + function: Callable[..., T], + interaction: ApplicationCommandInteraction, + /, + *args: Any, + **kwargs: Any, +) -> T: """Call a function utilizing ParamInfo""" cog_param, inter_param, paraminfos, injections = collect_params(function) formatted_kwargs = format_kwargs(interaction, cog_param, inter_param, *args, **kwargs) diff --git a/disnake/ext/commands/slash_core.py b/disnake/ext/commands/slash_core.py index 5c8dac4617..1aedca59be 100644 --- a/disnake/ext/commands/slash_core.py +++ b/disnake/ext/commands/slash_core.py @@ -190,8 +190,8 @@ def sub_command( self, name: LocalizedOptional = None, description: LocalizedOptional = None, - options: Optional[list] = None, - connectors: Optional[dict] = None, + options: Optional[List[Option]] = None, + connectors: Optional[Dict[str, str]] = None, extras: Optional[Dict[str, Any]] = None, **kwargs: Any, ) -> Callable[[CommandCallback], SubCommand]: @@ -270,7 +270,7 @@ def __init__( *, name: LocalizedOptional = None, description: LocalizedOptional = None, - options: Optional[list] = None, + options: Optional[List[Option]] = None, connectors: Optional[Dict[str, str]] = None, **kwargs: Any, ) -> None: @@ -341,11 +341,13 @@ def body(self) -> Option: return self.option async def _call_autocompleter( - self, param: str, inter: ApplicationCommandInteraction, user_input: str + self, param: str, inter: ApplicationCommandInteraction[Any], user_input: str ) -> Optional[Choices]: return await _call_autocompleter(self, param, inter, user_input) - async def invoke(self, inter: ApplicationCommandInteraction, *args: Any, **kwargs: Any) -> None: + async def invoke( + self, inter: ApplicationCommandInteraction[Any], *args: Any, **kwargs: Any + ) -> None: for k, v in self.connectors.items(): if k in kwargs: kwargs[v] = kwargs.pop(k) @@ -522,8 +524,8 @@ def sub_command( self, name: LocalizedOptional = None, description: LocalizedOptional = None, - options: Optional[list] = None, - connectors: Optional[dict] = None, + options: Optional[List[Option]] = None, + connectors: Optional[Dict[str, str]] = None, extras: Optional[Dict[str, Any]] = None, **kwargs: Any, ) -> Callable[[CommandCallback], SubCommand]: @@ -639,7 +641,7 @@ def autocomplete(self, option_name: str) -> Callable[[Callable], Callable]: return _autocomplete(self, option_name) async def _call_external_error_handlers( - self, inter: ApplicationCommandInteraction, error: CommandError + self, inter: ApplicationCommandInteraction[Any], error: CommandError ) -> None: stop_propagation = False cog = self.cog @@ -655,11 +657,11 @@ async def _call_external_error_handlers( inter.bot.dispatch("slash_command_error", inter, error) async def _call_autocompleter( - self, param: str, inter: ApplicationCommandInteraction, user_input: str + self, param: str, inter: ApplicationCommandInteraction[Any], user_input: str ) -> Optional[Choices]: return await _call_autocompleter(self, param, inter, user_input) - async def _call_relevant_autocompleter(self, inter: ApplicationCommandInteraction) -> None: + async def _call_relevant_autocompleter(self, inter: ApplicationCommandInteraction[Any]) -> None: chain, _ = inter.data._get_chain_and_kwargs() if len(chain) == 0: @@ -686,7 +688,7 @@ async def _call_relevant_autocompleter(self, inter: ApplicationCommandInteractio if choices is not None: await inter.response.autocomplete(choices=choices) - async def invoke_children(self, inter: ApplicationCommandInteraction) -> None: + async def invoke_children(self, inter: ApplicationCommandInteraction[Any]) -> None: chain, kwargs = inter.data._get_chain_and_kwargs() if len(chain) == 0: @@ -717,7 +719,7 @@ async def invoke_children(self, inter: ApplicationCommandInteraction) -> None: if not await subcmd._call_local_error_handler(inter, exc): raise - async def invoke(self, inter: ApplicationCommandInteraction) -> None: + async def invoke(self, inter: ApplicationCommandInteraction[Any]) -> None: await self.prepare(inter) try: diff --git a/disnake/ext/tasks/__init__.py b/disnake/ext/tasks/__init__.py index 6532c3d088..5f8080c3e6 100644 --- a/disnake/ext/tasks/__init__.py +++ b/disnake/ext/tasks/__init__.py @@ -701,7 +701,7 @@ def change_interval( T_co = TypeVar("T_co", covariant=True) -L_co = TypeVar("L_co", bound=Loop, covariant=True) +L_co = TypeVar("L_co", bound=Loop[Any], covariant=True) class Object(Protocol[T_co, P]): diff --git a/disnake/file.py b/disnake/file.py index 16bb7663bc..78d75d0cb5 100644 --- a/disnake/file.py +++ b/disnake/file.py @@ -54,7 +54,7 @@ class File: def __init__( self, - fp: Union[str, bytes, os.PathLike, io.BufferedIOBase], + fp: Union[str, bytes, os.PathLike[str], os.PathLike[bytes], io.BufferedIOBase], filename: Optional[str] = None, *, spoiler: bool = False, diff --git a/disnake/flags.py b/disnake/flags.py index ce9752f011..4b33aab8f9 100644 --- a/disnake/flags.py +++ b/disnake/flags.py @@ -95,7 +95,7 @@ def __repr__(self) -> str: return f"" -class alias_flag_value(flag_value): +class alias_flag_value(flag_value[T]): pass diff --git a/disnake/i18n.py b/disnake/i18n.py index 9a9ca32560..e164b130b2 100644 --- a/disnake/i18n.py +++ b/disnake/i18n.py @@ -289,7 +289,7 @@ def get(self, key: str) -> Optional[Dict[str, str]]: raise NotImplementedError # subtypes don't have to implement this - def load(self, path: Union[str, os.PathLike]) -> None: + def load(self, path: Union[str, os.PathLike[str]]) -> None: """Adds localizations from the provided path. Parameters @@ -354,7 +354,7 @@ def get(self, key: str) -> Optional[Dict[str, str]]: raise LocalizationKeyError(key) return data - def load(self, path: Union[str, os.PathLike]) -> None: + def load(self, path: Union[str, os.PathLike[str]]) -> None: """Adds localizations from the provided path to the store. If the path points to a file, the file gets loaded. If it's a directory, all ``.json`` files in that directory get loaded (non-recursive). diff --git a/disnake/interactions/application_command.py b/disnake/interactions/application_command.py index d25f6a2530..87608c0efd 100644 --- a/disnake/interactions/application_command.py +++ b/disnake/interactions/application_command.py @@ -330,10 +330,10 @@ def _get_chain_and_kwargs( # People asked about shorter aliases, let's see which one catches on the most -CommandInteraction = ApplicationCommandInteraction -CmdInteraction = ApplicationCommandInteraction -CommandInter = ApplicationCommandInteraction -CmdInter = ApplicationCommandInteraction -AppCommandInteraction = ApplicationCommandInteraction -AppCommandInter = ApplicationCommandInteraction -AppCmdInter = ApplicationCommandInteraction +CommandInteraction = ApplicationCommandInteraction[ClientT] +CmdInteraction = ApplicationCommandInteraction[ClientT] +CommandInter = ApplicationCommandInteraction[ClientT] +CmdInter = ApplicationCommandInteraction[ClientT] +AppCommandInteraction = ApplicationCommandInteraction[ClientT] +AppCommandInter = ApplicationCommandInteraction[ClientT] +AppCmdInter = ApplicationCommandInteraction[ClientT] diff --git a/disnake/interactions/base.py b/disnake/interactions/base.py index ce3b5cc89b..7b00682eef 100644 --- a/disnake/interactions/base.py +++ b/disnake/interactions/base.py @@ -70,7 +70,6 @@ from ..app_commands import Choices from ..client import Client from ..embeds import Embed - from ..ext.commands import AutoShardedBot, Bot from ..file import File from ..guild import GuildChannel, GuildMessageable from ..mentions import AllowedMentions @@ -91,8 +90,6 @@ InteractionChannel = Union[GuildChannel, Thread, PartialMessageable] - AnyBot = Union[Bot, AutoShardedBot] - MISSING: Any = utils.MISSING @@ -744,8 +741,8 @@ class InteractionResponse: "_response_type", ) - def __init__(self, parent: Interaction) -> None: - self._parent: Interaction = parent + def __init__(self, parent: Interaction[Any]) -> None: + self._parent: Interaction[Any] = parent self._response_type: Optional[InteractionResponseType] = None @property @@ -1172,7 +1169,7 @@ async def edit_message( if parent.type not in (InteractionType.component, InteractionType.modal_submit): raise InteractionNotEditable(parent) - parent = cast("Union[MessageInteraction, ModalInteraction]", parent) + parent = cast("Union[MessageInteraction[Any], ModalInteraction[Any]]", parent) message = parent.message # message in modal interactions only exists if modal was sent from component interaction if not message: @@ -1459,8 +1456,8 @@ async def cool_command(inter: disnake.ApplicationCommandInteraction): class _InteractionMessageState: __slots__ = ("_parent", "_interaction") - def __init__(self, interaction: Interaction, parent: ConnectionState) -> None: - self._interaction: Interaction = interaction + def __init__(self, interaction: Interaction[Any], parent: ConnectionState) -> None: + self._interaction: Interaction[Any] = interaction self._parent: ConnectionState = parent def _get_guild(self, guild_id): diff --git a/disnake/message.py b/disnake/message.py index 08d03da025..61e4978841 100644 --- a/disnake/message.py +++ b/disnake/message.py @@ -5,9 +5,9 @@ import asyncio import datetime import io +import os import re from base64 import b64decode, b64encode -from os import PathLike from typing import ( TYPE_CHECKING, Any, @@ -346,7 +346,7 @@ def flags(self) -> AttachmentFlags: async def save( self, - fp: Union[io.BufferedIOBase, PathLike], + fp: Union[io.BufferedIOBase, os.PathLike[str], os.PathLike[bytes]], *, seek_begin: bool = True, use_cached: bool = False, diff --git a/disnake/opus.py b/disnake/opus.py index 86a3ccbb70..5e611862f6 100644 --- a/disnake/opus.py +++ b/disnake/opus.py @@ -108,14 +108,14 @@ class DecoderStruct(ctypes.Structure): } -def _err_lt(result: int, func: Callable, args: List) -> int: +def _err_lt(result: int, func: Callable[..., Any], args: List[Any]) -> int: if result < OK: _log.info("error has happened in %s", func.__name__) raise OpusError(result) return result -def _err_ne(result: T, func: Callable, args: List) -> T: +def _err_ne(result: T, func: Callable[..., Any], args: List[Any]) -> T: ret = args[-1]._obj if ret.value != OK: _log.info("error has happened in %s", func.__name__) diff --git a/disnake/shard.py b/disnake/shard.py index 3903d413aa..83a2957025 100644 --- a/disnake/shard.py +++ b/disnake/shard.py @@ -11,6 +11,7 @@ Callable, Dict, List, + Literal, NoReturn, Optional, Tuple, @@ -96,7 +97,7 @@ def __init__( self.loop: asyncio.AbstractEventLoop = self._client.loop self._disconnect: bool = False self._reconnect = client._reconnect - self._backoff: ExponentialBackoff = ExponentialBackoff() + self._backoff: ExponentialBackoff[Literal[False]] = ExponentialBackoff() self._task: Optional[asyncio.Task] = None self._handled_exceptions: Tuple[Type[Exception], ...] = ( OSError, diff --git a/disnake/state.py b/disnake/state.py index f4885513d7..a069e333e1 100644 --- a/disnake/state.py +++ b/disnake/state.py @@ -89,6 +89,8 @@ from .webhook import Webhook if TYPE_CHECKING: + from typing_extensions import Concatenate + from .abc import MessageableChannel, PrivateChannel from .app_commands import APIApplicationCommand, ApplicationCommand from .client import Client @@ -110,6 +112,9 @@ Channel = Union[GuildChannel, VocalGuildChannel, PrivateChannel] PartialChannel = Union[Channel, PartialMessageable] +else: + Concatenate = Tuple # for the use-case of T[type, ...] Tuple works perfectly + class ChunkRequest: def __init__( @@ -189,9 +194,9 @@ class ConnectionState: def __init__( self, *, - dispatch: Callable, - handlers: Dict[str, Callable], - hooks: Dict[str, Callable], + dispatch: Callable[Concatenate[str, ...], Any], + handlers: Dict[str, Callable[..., Any]], + hooks: Dict[str, Callable[..., Any]], http: HTTPClient, loop: asyncio.AbstractEventLoop, max_messages: Optional[int] = 1000, @@ -211,9 +216,9 @@ def __init__( if self.max_messages is not None and self.max_messages <= 0: self.max_messages = 1000 - self.dispatch: Callable = dispatch - self.handlers: Dict[str, Callable] = handlers - self.hooks: Dict[str, Callable] = hooks + self.dispatch: Callable[Concatenate[str, ...], Any] = dispatch + self.handlers: Dict[str, Callable[..., Any]] = handlers + self.hooks: Dict[str, Callable[..., Any]] = hooks self.shard_count: Optional[int] = None self._ready_task: Optional[asyncio.Task] = None self.application_id: Optional[int] = None if application_id is None else int(application_id) @@ -935,7 +940,7 @@ def parse_interaction_create(self, data: gateway.InteractionCreateEvent) -> None # it wouldn't allow automatically narrowing the `data` union type based # on the `["type"]` field - interaction: Interaction + interaction: Interaction[Any] if data["type"] == 1: # PING interaction should never be received diff --git a/disnake/ui/item.py b/disnake/ui/item.py index 464eb4d588..a1fada9201 100644 --- a/disnake/ui/item.py +++ b/disnake/ui/item.py @@ -31,7 +31,7 @@ from ..types.components import Component as ComponentPayload from .view import View - ItemCallbackType = Callable[[Any, ItemT, MessageInteraction], Coroutine[Any, Any, Any]] + ItemCallbackType = Callable[[Any, ItemT, MessageInteraction[Any]], Coroutine[Any, Any, Any]] else: ParamSpec = TypeVar @@ -114,7 +114,7 @@ def __init__(self) -> None: def refresh_component(self, component: NestedComponent) -> None: return None - def refresh_state(self, interaction: MessageInteraction) -> None: + def refresh_state(self, interaction: MessageInteraction[Any]) -> None: return None @classmethod diff --git a/disnake/ui/modal.py b/disnake/ui/modal.py index adf21ffa9c..d533dc9a24 100644 --- a/disnake/ui/modal.py +++ b/disnake/ui/modal.py @@ -6,7 +6,7 @@ import os import sys import traceback -from typing import TYPE_CHECKING, Dict, List, Optional, Tuple, TypeVar, Union +from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, Union from ..enums import TextInputStyle from ..utils import MISSING @@ -14,7 +14,6 @@ from .text_input import TextInput if TYPE_CHECKING: - from ..client import Client from ..interactions.modal import ModalInteraction from ..state import ConnectionState from ..types.components import Modal as ModalPayload @@ -23,8 +22,6 @@ __all__ = ("Modal",) -ClientT = TypeVar("ClientT", bound="Client") - class Modal: """Represents a UI Modal. @@ -64,7 +61,7 @@ def __init__( self.title: str = title self.custom_id: str = os.urandom(16).hex() if custom_id is MISSING else custom_id - self.components: List[ActionRow] = rows + self.components: List[ActionRow[ModalUIComponent]] = rows self.timeout: float = timeout def __repr__(self) -> str: @@ -159,7 +156,7 @@ def add_text_input( ) ) - async def callback(self, interaction: ModalInteraction[ClientT], /) -> None: + async def callback(self, interaction: ModalInteraction[Any], /) -> None: """|coro| The callback associated with this modal. @@ -173,7 +170,7 @@ async def callback(self, interaction: ModalInteraction[ClientT], /) -> None: """ pass - async def on_error(self, error: Exception, interaction: ModalInteraction[ClientT]) -> None: + async def on_error(self, error: Exception, interaction: ModalInteraction[Any]) -> None: """|coro| A callback that is called when an error occurs. @@ -206,7 +203,7 @@ def to_components(self) -> ModalPayload: return payload - async def _scheduled_task(self, interaction: ModalInteraction) -> None: + async def _scheduled_task(self, interaction: ModalInteraction[Any]) -> None: try: await self.callback(interaction) except Exception as e: @@ -219,7 +216,7 @@ async def _scheduled_task(self, interaction: ModalInteraction) -> None: interaction.author.id, interaction.custom_id ) - def dispatch(self, interaction: ModalInteraction) -> None: + def dispatch(self, interaction: ModalInteraction[Any]) -> None: asyncio.create_task( self._scheduled_task(interaction), name=f"disnake-ui-modal-dispatch-{self.custom_id}" ) @@ -252,7 +249,7 @@ async def handle_timeout(self, user_id: int, modal_custom_id: str, timeout: floa else: await modal.on_timeout() - def dispatch(self, interaction: ModalInteraction) -> None: + def dispatch(self, interaction: ModalInteraction[Any]) -> None: key = (interaction.author.id, interaction.custom_id) modal = self._modals.get(key) if modal is not None: diff --git a/disnake/ui/select/base.py b/disnake/ui/select/base.py index cea174000d..d85ff2cc72 100644 --- a/disnake/ui/select/base.py +++ b/disnake/ui/select/base.py @@ -156,7 +156,7 @@ def width(self) -> int: def refresh_component(self, component: SelectMenuT) -> None: self._underlying = component - def refresh_state(self, interaction: MessageInteraction) -> None: + def refresh_state(self, interaction: MessageInteraction[Any]) -> None: self._selected_values = interaction.resolved_values # type: ignore @classmethod diff --git a/disnake/ui/view.py b/disnake/ui/view.py index 71c2965074..54dff54bd6 100644 --- a/disnake/ui/view.py +++ b/disnake/ui/view.py @@ -11,6 +11,7 @@ from itertools import groupby from typing import ( TYPE_CHECKING, + Any, Callable, ClassVar, Dict, @@ -318,7 +319,7 @@ def clear_items(self) -> Self: self.__weights.clear() return self - async def interaction_check(self, interaction: MessageInteraction) -> bool: + async def interaction_check(self, interaction: MessageInteraction[Any]) -> bool: """|coro| A callback that is called when an interaction happens within the view @@ -353,7 +354,9 @@ async def on_timeout(self) -> None: """ pass - async def on_error(self, error: Exception, item: Item, interaction: MessageInteraction) -> None: + async def on_error( + self, error: Exception, item: Item, interaction: MessageInteraction[Any] + ) -> None: """|coro| A callback that is called when an item's callback or :meth:`interaction_check` @@ -373,7 +376,7 @@ async def on_error(self, error: Exception, item: Item, interaction: MessageInter print(f"Ignoring exception in view {self} for item {item}:", file=sys.stderr) traceback.print_exception(error.__class__, error, error.__traceback__, file=sys.stderr) - async def _scheduled_task(self, item: Item, interaction: MessageInteraction): + async def _scheduled_task(self, item: Item, interaction: MessageInteraction[Any]): try: if self.timeout: self.__timeout_expiry = time.monotonic() + self.timeout @@ -403,7 +406,7 @@ def _dispatch_timeout(self) -> None: self.__stopped.set_result(True) asyncio.create_task(self.on_timeout(), name=f"disnake-ui-view-timeout-{self.id}") - def _dispatch_item(self, item: Item, interaction: MessageInteraction) -> None: + def _dispatch_item(self, item: Item, interaction: MessageInteraction[Any]) -> None: if self.__stopped.done(): return @@ -542,7 +545,7 @@ def remove_view(self, view: View) -> None: del self._synced_message_views[key] break - def dispatch(self, interaction: MessageInteraction) -> None: + def dispatch(self, interaction: MessageInteraction[Any]) -> None: self.__verify_integrity() message_id: Optional[int] = interaction.message and interaction.message.id component_type = try_enum_to_int(interaction.data.component_type) diff --git a/disnake/utils.py b/disnake/utils.py index 9061cd0f61..5ae1a6dd47 100644 --- a/disnake/utils.py +++ b/disnake/utils.py @@ -246,7 +246,7 @@ def isoformat_utc(dt: Optional[datetime.datetime]) -> Optional[str]: return None -def copy_doc(original: Callable) -> Callable[[T], T]: +def copy_doc(original: Callable[..., Any]) -> Callable[[T], T]: def decorator(overriden: T) -> T: overriden.__doc__ = original.__doc__ overriden.__signature__ = _signature(original) # type: ignore @@ -1009,7 +1009,7 @@ def add_param(param: Optional[str], desc_lines: List[str], maybe_type: Optional[ return options -def parse_docstring(func: Callable) -> _ParsedDocstring: +def parse_docstring(func: Callable[..., Any]) -> _ParsedDocstring: doc = _getdoc(func) if doc is None: return { diff --git a/disnake/webhook/async_.py b/disnake/webhook/async_.py index 7e1228a529..1d756d0c23 100644 --- a/disnake/webhook/async_.py +++ b/disnake/webhook/async_.py @@ -54,6 +54,8 @@ import datetime from types import TracebackType + from typing_extensions import Self + from ..abc import Snowflake from ..asset import AssetBytes from ..channel import ForumChannel, MediaChannel, StageChannel, TextChannel, VoiceChannel @@ -715,7 +717,7 @@ class _WebhookState(Generic[WebhookT]): def __init__( self, webhook: WebhookT, - parent: Optional[Union[ConnectionState, _WebhookState]], + parent: Optional[Union[ConnectionState, _WebhookState[Any]]], *, thread: Optional[Snowflake] = None, ) -> None: @@ -947,7 +949,7 @@ def __init__( state: Optional[ConnectionState] = None, ) -> None: self.auth_token: Optional[str] = token - self._state: Union[ConnectionState, _WebhookState] = state or _WebhookState( + self._state: Union[ConnectionState, _WebhookState[Self]] = state or _WebhookState( self, parent=state ) self._update(data) @@ -1036,8 +1038,8 @@ def avatar(self) -> Asset: """ if self._avatar is None: # Default is always blurple apparently - return Asset._from_default_avatar(self._state, 0) - return Asset._from_avatar(self._state, self.id, self._avatar) + return Asset._from_default_avatar(self._state, 0) # type: ignore + return Asset._from_avatar(self._state, self.id, self._avatar) # type: ignore class Webhook(BaseWebhook):