From 84c38f1f223d9d86ab3cbb3c2b936c002593e3f4 Mon Sep 17 00:00:00 2001 From: Rapptz Date: Mon, 21 Mar 2022 03:58:18 -0400 Subject: [PATCH] Ignore errors if it's already handled in app commands --- discord/app_commands/commands.py | 20 ++++++++++++++++++++ discord/app_commands/tree.py | 6 +++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/discord/app_commands/commands.py b/discord/app_commands/commands.py index 59b9c16af..10c1bfceb 100644 --- a/discord/app_commands/commands.py +++ b/discord/app_commands/commands.py @@ -454,6 +454,23 @@ class Command(Generic[GroupT, P, T]): if parent.parent is not None: await parent.parent.on_error(interaction, self, error) + def _has_any_error_handlers(self) -> bool: + if self.on_error is not None: + return True + + parent = self.parent + if parent is not None: + # Check if the on_error is overridden + if parent.__class__.on_error is not Group.on_error: + return True + + if parent.parent is not None: + parent_cls = parent.parent.__class__ + if parent_cls.on_error is not Group.on_error: + return True + + return False + async def _invoke_with_namespace(self, interaction: Interaction, namespace: Namespace) -> T: if not await self._check_can_run(interaction): raise CheckFailure(f'The check functions for command {self.name!r} failed.') @@ -766,6 +783,9 @@ class ContextMenu: # Type checker does not understand negative narrowing cases like this function return await async_all(f(interaction) for f in predicates) # type: ignore + def _has_any_error_handlers(self) -> bool: + return self.on_error is not None + async def _invoke(self, interaction: Interaction, arg: Any): try: if not await self._check_can_run(interaction): diff --git a/discord/app_commands/tree.py b/discord/app_commands/tree.py index fb728d0c1..62f2ab9bb 100644 --- a/discord/app_commands/tree.py +++ b/discord/app_commands/tree.py @@ -677,7 +677,8 @@ class CommandTree(Generic[ClientT]): A callback that is called when any command raises an :exc:`AppCommandError`. - The default implementation prints the traceback to stderr. + The default implementation prints the traceback to stderr if the command does + not have any error handlers attached to it. Parameters ----------- @@ -690,6 +691,9 @@ class CommandTree(Generic[ClientT]): """ if command is not None: + if command._has_any_error_handlers(): + return + print(f'Ignoring exception in command {command.name!r}:', file=sys.stderr) else: print(f'Ignoring exception in command tree:', file=sys.stderr)