Browse Source

[commands] Dispatch command_error on command exec error.

Provide fallback on_command_error - will only fire if no cog handlers and
no local handler.
Propagate exceptions in checks and argument parsing to bot.
pull/239/head
Khazhismel Kumykov 9 years ago
committed by Rapptz
parent
commit
33a69681fc
  1. 28
      discord/ext/commands/bot.py
  2. 15
      discord/ext/commands/core.py

28
discord/ext/commands/bot.py

@ -29,11 +29,12 @@ import discord
import inspect
import importlib
import sys
import traceback
from .core import GroupMixin, Command, command
from .view import StringView
from .context import Context
from .errors import CommandNotFound
from .errors import CommandNotFound, CommandError
from .formatter import HelpFormatter
def _get_variable(name):
@ -247,6 +248,26 @@ class Bot(GroupMixin, discord.Client):
coro = self._run_extra(event, event_name, *args, **kwargs)
discord.compat.create_task(coro, loop=self.loop)
@asyncio.coroutine
def on_command_error(self, exception, context):
"""|coro|
The default command error handler provided by the bot.
By default this prints to ``sys.stderr`` however it could be
overridden to have a different implementation.
This only fires if you do not specify any listeners for command error.
"""
if self.extra_events.get('on_command_error', None):
return
if hasattr(context.command, "on_error"):
return
print('Ignoring exception in command {}'.format(context.command), file=sys.stderr)
traceback.print_exception(type(exception), exception, exception.__traceback__, file=sys.stderr)
# utility "send_*" functions
def say(self, *args, **kwargs):
@ -618,7 +639,12 @@ class Bot(GroupMixin, discord.Client):
command = self.commands[invoker]
self.dispatch('command', command, ctx)
ctx.command = command
try:
yield from command.invoke(ctx)
except CommandError as e:
command.handle_local_error(e, ctx)
self.dispatch('command_error', e, ctx)
else:
self.dispatch('command_completion', command, ctx)
else:
exc = CommandNotFound('Command "{}" is not found'.format(invoker))

15
discord/ext/commands/core.py

@ -44,7 +44,10 @@ def inject_context(ctx, coro):
_internal_channel = ctx.message.channel
_internal_author = ctx.message.author
try:
ret = yield from coro(*args, **kwargs)
except Exception as e:
raise CommandError("Exception raised while executing command") from e
return ret
return wrapped
@ -306,7 +309,6 @@ class Command:
@asyncio.coroutine
def _parse_arguments(self, ctx):
try:
ctx.args = [] if self.instance is None else [self.instance]
ctx.kwargs = {}
args = ctx.args
@ -350,15 +352,9 @@ class Command:
args.append(transformed)
except RuntimeError:
break
except CommandError as e:
self.handle_local_error(e, ctx)
ctx.bot.dispatch('command_error', e, ctx)
return False
return True
def _verify_checks(self, ctx):
try:
if not self.enabled:
raise DisabledCommand('{0.name} command is disabled'.format(self))
@ -367,11 +363,6 @@ class Command:
if not self.can_run(ctx):
raise CheckFailure('The check functions for command {0.name} failed.'.format(self))
except CommandError as exc:
self.handle_local_error(exc, ctx)
ctx.bot.dispatch('command_error', exc, ctx)
return False
return True
@asyncio.coroutine

Loading…
Cancel
Save