diff options
| author | Rapptz <[email protected]> | 2021-06-05 08:18:45 -0400 |
|---|---|---|
| committer | Rapptz <[email protected]> | 2021-06-05 08:22:44 -0400 |
| commit | 876b1e0f3eac83b6cf7b965b42f37807ca10f873 (patch) | |
| tree | 21cc6a21eed8f540ac2e88bbbd6b49a2408c551c | |
| parent | Fix DM channel permissions not having read_messages (diff) | |
| download | discord.py-876b1e0f3eac83b6cf7b965b42f37807ca10f873.tar.xz discord.py-876b1e0f3eac83b6cf7b965b42f37807ca10f873.zip | |
Add View.on_error callback for swallowed exceptions
| -rw-r--r-- | discord/ui/view.py | 41 |
1 files changed, 31 insertions, 10 deletions
diff --git a/discord/ui/view.py b/discord/ui/view.py index 4868196d..38ca9763 100644 --- a/discord/ui/view.py +++ b/discord/ui/view.py @@ -27,6 +27,7 @@ from typing import Any, Callable, ClassVar, Dict, Iterator, List, Optional, Sequ from functools import partial from itertools import groupby +import traceback import asyncio import sys import time @@ -252,7 +253,8 @@ class View: .. note:: If an exception occurs within the body then the interaction - check is considered failed. + check then :meth:`on_error` is called and it is considered + a failure. Parameters ----------- @@ -273,18 +275,37 @@ class View: """ pass + async def on_error(self, error: Exception, item: Item, interaction: Interaction) -> None: + """|coro| + + A callback that is called when an item's callback or :meth:`interaction_check` + fails with an error. + + The default implementation prints the traceback to stderr. + + Parameters + ----------- + error: :class:`Exception` + The exception that was raised. + item: :class:`Item` + The item that failed the dispatch. + interaction: :class:`~discord.Interaction` + The interaction that led to the failure. + """ + 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, state: Any, item: Item, interaction: Interaction): try: allow = await self.interaction_check(interaction) - except Exception: - allow = False - - if not allow: - return - - await item.callback(interaction) - if not interaction.response._responded: - await interaction.response.defer() + if not allow: + return + + await item.callback(interaction) + if not interaction.response._responded: + await interaction.response.defer() + except Exception as e: + return await self.on_error(e, item, interaction) def _start_listening(self, store: ViewStore) -> None: self._cancel_callback = partial(store.remove_view) |