discord.py icon indicating copy to clipboard operation
discord.py copied to clipboard

Pass error raised in subcommands to local error handler of its parent group command.

Open weibeu opened this issue 6 years ago • 1 comments

The Problem

If several subcommands of a certain group command raises same error, we will have to add local error handler method to each of these subcommands which makes us repeat same block of codes. Obviously we can add it to our global error handler but its not wise to do so if that error is meaningful only for those particular sets of group commands. It will enable group commands to have its own single error handler method for its several subcommands.

The Ideal Solution

@commands.group()
async def profile(ctx, user=None):
    pass

@profile.error
async def profile_error(ctx, error):
    if isinstance(error, ProfileNotCreatedError):
        await ctx.send("You have not created your profile yet. Use ;profile create command now to create your profile.")

@profile.command()
async def name(ctx):
    raise ProfileNotCreatedError

@profile.command()
async def description(ctx):
    raise ProfileNotCreatedError

@profile.command()
async def color(ctx):
    raise ProfileNotCreatedError

The Current Solution

@commands.group()
async def profile(ctx, user=None):
    pass

@profile.command()
async def name(ctx):
    raise ProfileNotCreatedError

@name.error
async def name_error(ctx, error):
    if isinstance(error, ProfileNotCreatedError):
        await ctx.send("You have not created your profile yet. Use ;profile create command now to create your profile.")

@profile.command()
async def description(ctx):
    raise ProfileNotCreatedError

@description.error
async def description_error(ctx, error):
    if isinstance(error, ProfileNotCreatedError):
        await ctx.send("You have not created your profile yet. Use ;profile create command now to create your profile.")

@profile.command()
async def color(ctx):
    raise ProfileNotCreatedError

@color.error
async def color_error(ctx, error):
    if isinstance(error, ProfileNotCreatedError):
        await ctx.send("You have not created your profile yet. Use ;profile create command now to create your profile.")

OR


class MyErrorHandler(commands.Cog):

    @Cog.listener()
    async def on_command_error(self, ctx, error):
        if isinstance(error, ProfileNotCreatedError):
            await ctx.send("You have not created your profile yet. Use ;profile create command now to create your profile.")

def setup(bot):
    bot.add_cog(MyErrorHandler(bot))

Summary

This feature will enable us to organise commands and their own Exceptions in a cleaner way, separating common global Exceptions from Exception raised from some particular interrelated subcommands of a group command.

weibeu avatar Apr 22 '19 04:04 weibeu

You can implement this behavior fairly easily with a command subclass, by calling command.root_parent.on_error inside command.dispatch_error. See: https://github.com/Rapptz/discord.py/blob/master/discord/ext/commands/core.py#L312-L333

That said, this behavior feels fairly niche for mainline implementation.

Vexs avatar Apr 22 '19 04:04 Vexs