[commands] Redesign extension exception flow.

Instead of raising a whole variety of exceptions, they are now wrapped
into ExtensionError derived classes.

* ExtensionAlreadyLoaded
	* Raised when an extension is already loaded in Bot.load_extension
* ExtensionNotLoaded
	* Raised when an extension is not loaded, e.g. Bot.unload_extension
* NoEntryPointError
	* Raised when an extension does not have a `setup` function.
* ExtensionFailed
	* Raised when an extension's `setup` function fails.
* ExtensionNotFound
	* Raised when an extension's module import fails.
This commit is contained in:
Rapptz
2019-03-19 07:35:56 -04:00
parent 26e9b5bfac
commit d9e54d7dd3
3 changed files with 140 additions and 21 deletions

View File

@ -34,7 +34,9 @@ __all__ = ['CommandError', 'MissingRequiredArgument', 'BadArgument',
'MissingPermissions', 'BotMissingPermissions', 'ConversionError',
'BadUnionArgument', 'ArgumentParsingError',
'UnexpectedQuoteError', 'InvalidEndOfQuotedStringError',
'ExpectedClosingQuoteError', ]
'ExpectedClosingQuoteError', 'ExtensionError', 'ExtensionAlreadyLoaded',
'ExtensionNotLoaded', 'NoEntryPointError', 'ExtensionFailed',
'ExtensionNotFound' ]
class CommandError(DiscordException):
r"""The base exception type for all command related errors.
@ -283,3 +285,80 @@ class ExpectedClosingQuoteError(ArgumentParsingError):
def __init__(self, close_quote):
self.close_quote = close_quote
super().__init__('Expected closing {}.'.format(close_quote))
class ExtensionError(DiscordException):
"""Base exception for extension related errors.
This inherits from :exc:`~discord.DiscordException`.
Parameter
-----------
name: :class:`str`
The extension that had an error.
"""
def __init__(self, message=None, *args, name):
self.name = name
message = message or 'Extension {!r} had an error.'.format(name)
# clean-up @everyone and @here mentions
m = message.replace('@everyone', '@\u200beveryone').replace('@here', '@\u200bhere')
super().__init__(m, *args)
class ExtensionAlreadyLoaded(ExtensionError):
"""An exception raised when an extension has already been loaded.
This inherits from :exc:`ExtensionError`
"""
def __init__(self, name):
super().__init__('Extension {!r} is already loaded.'.format(name), name=name)
class ExtensionNotLoaded(ExtensionError):
"""An exception raised when an extension was not loaded.
This inherits from :exc:`ExtensionError`
"""
def __init__(self, name):
super().__init__('Extension {!r} has not been loaded.'.format(name), name=name)
class NoEntryPointError(ExtensionError):
"""An exception raised when an extension does not have a ``setup`` entry point function.
This inherits from :exc:`ExtensionError`
"""
def __init__(self, name):
super().__init__("Extension {!r} has no 'setup' function.".format(name), name=name)
class ExtensionFailed(ExtensionError):
"""An exception raised when an extension failed to load during execution of the ``setup`` entry point.
This inherits from :exc:`ExtensionError`
Attributes
-----------
name: :class:`str`
The extension that had the error.
original: :exc:`Exception`
The original exception that was raised. You can also get this via
the ``__cause__`` attribute.
"""
def __init__(self, name, original):
self.original = original
fmt = 'Extension {0!r} raised an error: {1.__class__.__name__}: {1}'
super().__init__(fmt.format(name, original), name=name)
class ExtensionNotFound(ExtensionError):
"""An exception raised when an extension failed to be imported.
This inherits from :exc:`ExtensionError`
Attributes
-----------
name: :class:`str`
The extension that had the error.
original: :exc:`ImportError`
The original exception that was raised. You can also get this via
the ``__cause__`` attribute.
"""
def __init__(self, name, original):
self.original = original
fmt = 'Extension {0!r} could not be loaded.'
super().__init__(fmt.format(name), name=name)