Browse Source

Add View.on_error callback for swallowed exceptions

pull/7023/head
Rapptz 4 years ago
parent
commit
876b1e0f3e
  1. 41
      discord/ui/view.py

41
discord/ui/view.py

@ -27,6 +27,7 @@ from typing import Any, Callable, ClassVar, Dict, Iterator, List, Optional, Sequ
from functools import partial from functools import partial
from itertools import groupby from itertools import groupby
import traceback
import asyncio import asyncio
import sys import sys
import time import time
@ -252,7 +253,8 @@ class View:
.. note:: .. note::
If an exception occurs within the body then the interaction 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 Parameters
----------- -----------
@ -273,18 +275,37 @@ class View:
""" """
pass 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): async def _scheduled_task(self, state: Any, item: Item, interaction: Interaction):
try: try:
allow = await self.interaction_check(interaction) allow = await self.interaction_check(interaction)
except Exception: if not allow:
allow = False return
if not allow: await item.callback(interaction)
return if not interaction.response._responded:
await interaction.response.defer()
await item.callback(interaction) except Exception as e:
if not interaction.response._responded: return await self.on_error(e, item, interaction)
await interaction.response.defer()
def _start_listening(self, store: ViewStore) -> None: def _start_listening(self, store: ViewStore) -> None:
self._cancel_callback = partial(store.remove_view) self._cancel_callback = partial(store.remove_view)

Loading…
Cancel
Save