[commands] Add Command.ignore_extra attribute to ignore extra arguments
This allows you to strictly require a number of arguments. The default behaviour in this case is still `True`, since it would be a breaking change otherwise and is a sane default. However if someone would want to set this to `False`, they would receive an exception of type `TooManyArguments` if too many arguments are passed to a command. Hopefully this removes the uses of `ctx.message.content == 'stuff'` inside commands.
This commit is contained in:
		| @@ -100,10 +100,10 @@ class Command: | |||||||
|     description : str |     description : str | ||||||
|         The message prefixed into the default help command. |         The message prefixed into the default help command. | ||||||
|     hidden : bool |     hidden : bool | ||||||
|         If ``True``, the default help command does not show this in the |         If ``True``\, the default help command does not show this in the | ||||||
|         help output. |         help output. | ||||||
|     no_pm : bool |     no_pm : bool | ||||||
|         If ``True``, then the command is not allowed to be executed in |         If ``True``\, then the command is not allowed to be executed in | ||||||
|         private messages. Defaults to ``False``. Note that if it is executed |         private messages. Defaults to ``False``. Note that if it is executed | ||||||
|         in private messages, then :func:`on_command_error` and local error handlers |         in private messages, then :func:`on_command_error` and local error handlers | ||||||
|         are called with the :exc:`NoPrivateMessage` error. |         are called with the :exc:`NoPrivateMessage` error. | ||||||
| @@ -114,6 +114,11 @@ class Command: | |||||||
|         regular matter rather than passing the rest completely raw. If ``True`` |         regular matter rather than passing the rest completely raw. If ``True`` | ||||||
|         then the keyword-only argument will pass in the rest of the arguments |         then the keyword-only argument will pass in the rest of the arguments | ||||||
|         in a completely raw matter. Defaults to ``False``. |         in a completely raw matter. Defaults to ``False``. | ||||||
|  |     ignore_extra : bool | ||||||
|  |         If ``True``\, ignores extraneous strings passed to a command if all its | ||||||
|  |         requirements are met (e.g. ``?foo a b c`` when only expecting ``a`` | ||||||
|  |         and ``b``). Otherwise :func:`on_command_error` and local error handlers | ||||||
|  |         are called with :exc:`TooManyArguments`. Defaults to ``True``. | ||||||
|     """ |     """ | ||||||
|     def __init__(self, name, callback, **kwargs): |     def __init__(self, name, callback, **kwargs): | ||||||
|         self.name = name |         self.name = name | ||||||
| @@ -134,6 +139,7 @@ class Command: | |||||||
|         self.checks = kwargs.get('checks', []) |         self.checks = kwargs.get('checks', []) | ||||||
|         self.module = inspect.getmodule(callback) |         self.module = inspect.getmodule(callback) | ||||||
|         self.no_pm = kwargs.get('no_pm', False) |         self.no_pm = kwargs.get('no_pm', False) | ||||||
|  |         self.ignore_extra = kwargs.get('ignore_extra', True) | ||||||
|         self.instance = None |         self.instance = None | ||||||
|         self.parent = None |         self.parent = None | ||||||
|  |  | ||||||
| @@ -388,6 +394,11 @@ class Command: | |||||||
|                     except RuntimeError: |                     except RuntimeError: | ||||||
|                         break |                         break | ||||||
|  |  | ||||||
|  |         if not self.ignore_extra: | ||||||
|  |             if not view.eof: | ||||||
|  |                 raise TooManyArguments('Too many arguments passed to ' + self.qualified_name) | ||||||
|  |  | ||||||
|  |  | ||||||
|     def _verify_checks(self, ctx): |     def _verify_checks(self, ctx): | ||||||
|         if not self.enabled: |         if not self.enabled: | ||||||
|             raise DisabledCommand('{0.name} command is disabled'.format(self)) |             raise DisabledCommand('{0.name} command is disabled'.format(self)) | ||||||
|   | |||||||
| @@ -28,7 +28,7 @@ from discord.errors import DiscordException | |||||||
|  |  | ||||||
| __all__ = [ 'CommandError', 'MissingRequiredArgument', 'BadArgument', | __all__ = [ 'CommandError', 'MissingRequiredArgument', 'BadArgument', | ||||||
|            'NoPrivateMessage', 'CheckFailure', 'CommandNotFound', |            'NoPrivateMessage', 'CheckFailure', 'CommandNotFound', | ||||||
|            'DisabledCommand', 'CommandInvokeError' ] |            'DisabledCommand', 'CommandInvokeError', 'TooManyArguments' ] | ||||||
|  |  | ||||||
| class CommandError(DiscordException): | class CommandError(DiscordException): | ||||||
|     """The base exception type for all command related errors. |     """The base exception type for all command related errors. | ||||||
| @@ -94,3 +94,9 @@ class CommandInvokeError(CommandError): | |||||||
|     def __init__(self, e): |     def __init__(self, e): | ||||||
|         self.original = e |         self.original = e | ||||||
|         super().__init__('Command raised an exception: {0.__class__.__name__}: {0}'.format(e)) |         super().__init__('Command raised an exception: {0.__class__.__name__}: {0}'.format(e)) | ||||||
|  |  | ||||||
|  | class TooManyArguments(CommandError): | ||||||
|  |     """Exception raised when the command was passed too many arguments and its | ||||||
|  |     :attr:`Command.ignore_extra` attribute was not set to ``True``. | ||||||
|  |     """ | ||||||
|  |     pass | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user