Created
September 28, 2019 18:39
-
-
Save leonhard-s/ece426c2315834f5e0b4af600181b25e to your computer and use it in GitHub Desktop.
Adds standardised attributes to BadArgument exceptions in discord.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"""Adds standardised attributes to BadArgument exceptions in discord.py. | |
The default `BadArgument` exception does not have any extra arguments, | |
and the error messages generated are too different to easily convert | |
into user-facing error messages. | |
This extension fixes that by capturing any `BadArgument` exceptions | |
raised and re-raising them with three extra arguments: | |
* argument {str} -- The string that could not be converted | |
* annotation {Any} -- The object the argument was annotated with | |
* type_name {str} -- A formatted name of the target type | |
The `type_name` argument will generally return the name of the class. | |
If the class name ends in "Converter", this suffix is stripped off. | |
""" | |
import inspect | |
from typing import Any | |
from discord.ext import commands | |
async def _inject_argument_info(self, ctx: commands.Context, | |
converter: commands.Converter, argument: str, | |
param: inspect.Parameter) -> Any: | |
"""Add argument and converter info to `BadArgument` exceptions. | |
This method is a replacement for the original `_actual_conversion` | |
method of the `commands.Command` class. It forwards the call to the | |
original method, but injects any `commands.BadArgument` exceptions | |
raised with additional attributes to facilitate error message | |
generation. | |
""" | |
# NOTE: This method forwards the call to the original _actual_conversion | |
# method. Whenever a BadArgument exception is raised, it is injected with | |
# useful arguments before being re-raised. | |
# This should be more-or-less invisible to any other modules, aside from | |
# the additional call and the injected arguments. | |
try: | |
return await self._original_actual_conversion(ctx, converter, | |
argument, param) | |
except commands.BadArgument as err: | |
err.argument = argument | |
err.annotation = param.annotation | |
# Remove the "Converter"-suffix of object-specific converters. This | |
# turns "MemberConverter" into "Member", etc. | |
err.type_name = param.annotation.__name__.split('Converter')[:-1] | |
raise err | |
def setup(bot: commands.Bot) -> None: | |
"""Entry point for the bot extension loader.""" | |
cmd_cls = commands.Command | |
# Store the original converter | |
cmd_cls._original_actual_conversion = cmd_cls._actual_conversion | |
# Add the BadArgument attribute injector | |
cmd_cls._actual_conversion = _inject_argument_info | |
def teardown(bot: commands.Bot) -> None: | |
"""Clean-up utility when unloading the extension.""" | |
cmd_cls = commands.Command | |
# Restore the original converter | |
cmd_cls._actual_conversion = cmd_cls._original_actual_conversion | |
# Remove the backup | |
del cmd_cls._original_actual_conversion |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment