diff --git a/.gitignore b/.gitignore index 67f1281f4d..4460ddcee5 100644 --- a/.gitignore +++ b/.gitignore @@ -31,7 +31,14 @@ venvs/ .coverage* coverage.xml __pypackages__/ +# .pdm.toml - pdm config used & produced by pdm <=2.4 .pdm.toml +# since .pdm.toml was an alternative to pyproject.toml +# store of pdm config (and also often only contained local +# python path), it was renamed to pdm.toml (which, unlike +# .pdm.toml, should be commited to VCS) and python path from it +# was extracted into a single-line .pdm-python since pdm 2.5.0b +.pdm-python pdm.lock !test_bot/locale/*.json diff --git a/disnake/ext/commands/_types.py b/disnake/ext/commands/_types.py index eb90ee0a42..abceb0ee37 100644 --- a/disnake/ext/commands/_types.py +++ b/disnake/ext/commands/_types.py @@ -3,6 +3,8 @@ from typing import TYPE_CHECKING, Any, Callable, Coroutine, TypeVar, Union if TYPE_CHECKING: + from disnake import ApplicationCommandInteraction as AppCmdInter + from .cog import Cog from .context import Context from .errors import CommandError @@ -13,6 +15,12 @@ MaybeCoro = Union[T, Coro[T]] CoroFunc = Callable[..., Coro[Any]] +# This is explicitly "Global" to highlight the fact that this type +# should not be used with per-command checks +GlobalAppCheck = Callable[["AppCmdInter"], MaybeCoro[bool]] +AppCheck = Union[ + Callable[["Cog", "AppCmdInter"], MaybeCoro[bool]], Callable[["AppCmdInter"], MaybeCoro[bool]] +] Check = Union[ Callable[["Cog", "Context[Any]"], MaybeCoro[bool]], Callable[["Context[Any]"], MaybeCoro[bool]] ] diff --git a/disnake/ext/commands/base_core.py b/disnake/ext/commands/base_core.py index c21cc5f2d1..5e1ca0483d 100644 --- a/disnake/ext/commands/base_core.py +++ b/disnake/ext/commands/base_core.py @@ -33,7 +33,7 @@ from disnake.interactions import ApplicationCommandInteraction - from ._types import Check, Coro, Error, Hook + from ._types import AppCheck, Coro, Error, Hook from .cog import Cog ApplicationCommandInteractionT = TypeVar( @@ -155,7 +155,7 @@ def __init__(self, func: CommandCallback, *, name: Optional[str] = None, **kwarg except AttributeError: checks = kwargs.get("checks", []) - self.checks: List[Check] = checks + self.checks: List[AppCheck] = checks try: cooldown = func.__commands_cooldown__ @@ -253,7 +253,7 @@ def default_member_permissions(self) -> Optional[Permissions]: def callback(self) -> CommandCallback: return self._callback - def add_check(self, func: Check) -> None: + def add_check(self, func: AppCheck) -> None: """Adds a check to the application command. This is the non-decorator interface to :func:`.check`. @@ -265,7 +265,7 @@ def add_check(self, func: Check) -> None: """ self.checks.append(func) - def remove_check(self, func: Check) -> None: + def remove_check(self, func: AppCheck) -> None: """Removes a check from the application command. This function is idempotent and will not raise an exception diff --git a/disnake/ext/commands/bot_base.py b/disnake/ext/commands/bot_base.py index d55dc63490..b228fbcbaf 100644 --- a/disnake/ext/commands/bot_base.py +++ b/disnake/ext/commands/bot_base.py @@ -38,7 +38,7 @@ from disnake.message import Message - from ._types import Check, CoroFunc, MaybeCoro + from ._types import AppCheck, CoroFunc, MaybeCoro __all__ = ( "when_mentioned", @@ -162,8 +162,8 @@ def __init__( self.command_prefix = command_prefix - self._checks: List[Check] = [] - self._check_once: List[Check] = [] + self._checks: List[AppCheck] = [] + self._check_once: List[AppCheck] = [] self._before_invoke: Optional[CoroFunc] = None self._after_invoke: Optional[CoroFunc] = None @@ -211,7 +211,7 @@ async def on_command_error(self, context: Context, exception: errors.CommandErro def add_check( self, - func: Check, + func: AppCheck, *, call_once: bool = False, ) -> None: @@ -236,7 +236,7 @@ def add_check( def remove_check( self, - func: Check, + func: AppCheck, *, call_once: bool = False, ) -> None: diff --git a/disnake/ext/commands/cog.py b/disnake/ext/commands/cog.py index a0ec377d53..18860fcdd5 100644 --- a/disnake/ext/commands/cog.py +++ b/disnake/ext/commands/cog.py @@ -787,30 +787,30 @@ def _inject(self, bot: AnyBot) -> Self: # Add application command checks if cls.bot_slash_command_check is not Cog.bot_slash_command_check: - bot.add_app_command_check(self.bot_slash_command_check, slash_commands=True) # type: ignore + bot.add_app_command_check(self.bot_slash_command_check, slash_commands=True) if cls.bot_user_command_check is not Cog.bot_user_command_check: - bot.add_app_command_check(self.bot_user_command_check, user_commands=True) # type: ignore + bot.add_app_command_check(self.bot_user_command_check, user_commands=True) if cls.bot_message_command_check is not Cog.bot_message_command_check: - bot.add_app_command_check(self.bot_message_command_check, message_commands=True) # type: ignore + bot.add_app_command_check(self.bot_message_command_check, message_commands=True) # Add app command one-off checks if cls.bot_slash_command_check_once is not Cog.bot_slash_command_check_once: bot.add_app_command_check( - self.bot_slash_command_check_once, # type: ignore + self.bot_slash_command_check_once, call_once=True, slash_commands=True, ) if cls.bot_user_command_check_once is not Cog.bot_user_command_check_once: bot.add_app_command_check( - self.bot_user_command_check_once, call_once=True, user_commands=True # type: ignore + self.bot_user_command_check_once, call_once=True, user_commands=True ) if cls.bot_message_command_check_once is not Cog.bot_message_command_check_once: bot.add_app_command_check( - self.bot_message_command_check_once, # type: ignore + self.bot_message_command_check_once, call_once=True, message_commands=True, ) @@ -857,32 +857,32 @@ def _eject(self, bot: AnyBot) -> None: # Remove application command checks if cls.bot_slash_command_check is not Cog.bot_slash_command_check: - bot.remove_app_command_check(self.bot_slash_command_check, slash_commands=True) # type: ignore + bot.remove_app_command_check(self.bot_slash_command_check, slash_commands=True) if cls.bot_user_command_check is not Cog.bot_user_command_check: - bot.remove_app_command_check(self.bot_user_command_check, user_commands=True) # type: ignore + bot.remove_app_command_check(self.bot_user_command_check, user_commands=True) if cls.bot_message_command_check is not Cog.bot_message_command_check: - bot.remove_app_command_check(self.bot_message_command_check, message_commands=True) # type: ignore + bot.remove_app_command_check(self.bot_message_command_check, message_commands=True) # Remove app command one-off checks if cls.bot_slash_command_check_once is not Cog.bot_slash_command_check_once: bot.remove_app_command_check( - self.bot_slash_command_check_once, # type: ignore + self.bot_slash_command_check_once, call_once=True, slash_commands=True, ) if cls.bot_user_command_check_once is not Cog.bot_user_command_check_once: bot.remove_app_command_check( - self.bot_user_command_check_once, # type: ignore + self.bot_user_command_check_once, call_once=True, user_commands=True, ) if cls.bot_message_command_check_once is not Cog.bot_message_command_check_once: bot.remove_app_command_check( - self.bot_message_command_check_once, # type: ignore + self.bot_message_command_check_once, call_once=True, message_commands=True, ) diff --git a/disnake/ext/commands/interaction_bot_base.py b/disnake/ext/commands/interaction_bot_base.py index 25308c3649..3bcdab31c4 100644 --- a/disnake/ext/commands/interaction_bot_base.py +++ b/disnake/ext/commands/interaction_bot_base.py @@ -54,7 +54,7 @@ ) from disnake.permissions import Permissions - from ._types import Check, CoroFunc + from ._types import CoroFunc, GlobalAppCheck from .base_core import CogT, CommandCallback, InteractionCommandCallback P = ParamSpec("P") @@ -199,12 +199,12 @@ def __init__( self._command_sync_flags = command_sync_flags self._sync_queued: asyncio.Lock = asyncio.Lock() - self._slash_command_checks = [] - self._slash_command_check_once = [] - self._user_command_checks = [] - self._user_command_check_once = [] - self._message_command_checks = [] - self._message_command_check_once = [] + self._slash_command_checks: List[GlobalAppCheck] = [] + self._slash_command_check_once: List[GlobalAppCheck] = [] + self._user_command_checks: List[GlobalAppCheck] = [] + self._user_command_check_once: List[GlobalAppCheck] = [] + self._message_command_checks: List[GlobalAppCheck] = [] + self._message_command_check_once: List[GlobalAppCheck] = [] self._before_slash_command_invoke = None self._after_slash_command_invoke = None @@ -991,7 +991,7 @@ async def on_message_command_error( def add_app_command_check( self, - func: Check, + func: GlobalAppCheck, *, call_once: bool = False, slash_commands: bool = False, @@ -1039,7 +1039,7 @@ def add_app_command_check( def remove_app_command_check( self, - func: Check, + func: GlobalAppCheck, *, call_once: bool = False, slash_commands: bool = False, @@ -1091,35 +1091,32 @@ def remove_app_command_check( except ValueError: pass - def slash_command_check(self, func: T) -> T: + def slash_command_check(self, func: GlobalAppCheck) -> GlobalAppCheck: """Similar to :meth:`.check` but for slash commands.""" - # T was used instead of Check to ensure the type matches on return - self.add_app_command_check(func, slash_commands=True) # type: ignore + self.add_app_command_check(func, slash_commands=True) return func - def slash_command_check_once(self, func: CFT) -> CFT: + def slash_command_check_once(self, func: GlobalAppCheck) -> GlobalAppCheck: """Similar to :meth:`.check_once` but for slash commands.""" self.add_app_command_check(func, call_once=True, slash_commands=True) return func - def user_command_check(self, func: T) -> T: + def user_command_check(self, func: GlobalAppCheck) -> GlobalAppCheck: """Similar to :meth:`.check` but for user commands.""" - # T was used instead of Check to ensure the type matches on return - self.add_app_command_check(func, user_commands=True) # type: ignore + self.add_app_command_check(func, user_commands=True) return func - def user_command_check_once(self, func: CFT) -> CFT: + def user_command_check_once(self, func: GlobalAppCheck) -> GlobalAppCheck: """Similar to :meth:`.check_once` but for user commands.""" self.add_app_command_check(func, call_once=True, user_commands=True) return func - def message_command_check(self, func: T) -> T: + def message_command_check(self, func: GlobalAppCheck) -> GlobalAppCheck: """Similar to :meth:`.check` but for message commands.""" - # T was used instead of Check to ensure the type matches on return - self.add_app_command_check(func, message_commands=True) # type: ignore + self.add_app_command_check(func, message_commands=True) return func - def message_command_check_once(self, func: CFT) -> CFT: + def message_command_check_once(self, func: GlobalAppCheck) -> GlobalAppCheck: """Similar to :meth:`.check_once` but for message commands.""" self.add_app_command_check(func, call_once=True, message_commands=True) return func @@ -1131,10 +1128,7 @@ def application_command_check( slash_commands: bool = False, user_commands: bool = False, message_commands: bool = False, - ) -> Callable[ - [Callable[[ApplicationCommandInteraction], Any]], - Callable[[ApplicationCommandInteraction], Any], - ]: + ) -> Callable[[GlobalAppCheck], GlobalAppCheck]: """A decorator that adds a global application command check to the bot. A global check is similar to a :func:`check` that is applied @@ -1174,12 +1168,9 @@ def check_app_commands(inter): user_commands = True message_commands = True - def decorator( - func: Callable[[ApplicationCommandInteraction], Any] - ) -> Callable[[ApplicationCommandInteraction], Any]: - # T was used instead of Check to ensure the type matches on return + def decorator(func: GlobalAppCheck) -> GlobalAppCheck: self.add_app_command_check( - func, # type: ignore + func, call_once=call_once, slash_commands=slash_commands, user_commands=user_commands,