Нажмите: Настроить обработку ошибок "Отсутствует аргумент", переопределив функцию show UsageError - PullRequest
1 голос
/ 27 апреля 2020

В настоящее время я пытаюсь настроить обработку ошибок, когда была дана команда, без предоставления необходимых аргументов с помощью Click. Согласно этому вопросу SO это можно сделать, переопределив show функцию click.exceptions.UsageError. Тем не менее, я попытался изменить предоставленное решение, но не смог заставить его работать.

В моем случае я хочу получить команду, которая должна быть выполнена (но не выполнена из-за пропущенных аргументов) и, в зависимости от введенной команды, я хочу обрабатывать дальше. Мой пример кода выглядит следующим образом:

@click.group(cls=MyGroup)
def myapp():
    pass

@myapp.command()
@click.argument('myarg',type=str)
def mycommand(myarg: str) -> None:
    do_stuff(myarg)

Так что, если команда была чем-то вроде myapp mycommand и она пропускает необходимые аргументы, я хочу обработать ее индивидуально. Некоторое время я искал, но не смог выяснить, КАК извлечь команду (я попытался передать контекст, но насколько я читал, UsageError не получает никакого контекста, переданного при инициализации).

I Буду благодарен за любые подсказки или идеи.

РЕДАКТИРОВАТЬ: Реализация myGroup выглядит следующим образом:

class myGroup(click.Group):
"""
Customize help order and get_command
https://stackoverflow.com/a/47984810/713980
"""

def __init__(self, *args, **kwargs):
    self.help_priorities = {}
    super(myGroup, self).__init__(*args, **kwargs)

def get_help(self, ctx):
    self.list_commands = self.list_commands_for_help
    return super(myGroup, self).get_help(ctx)

def list_commands_for_help(self, ctx):
    """reorder the list of commands when listing the help"""
    commands = super(myGroup, self).list_commands(ctx)
    return (c[1] for c in sorted((self.help_priorities.get(command, 1000), command) for command in commands))

def command(self, *args, **kwargs):
    """Behaves the same as `click.Group.command()` except capture
    a priority for listing command names in help.
    """
    help_priority = kwargs.pop('help_priority', 1000)
    help_priorities = self.help_priorities

    def decorator(f):
        cmd = super(myGroup, self).command(*args, **kwargs)(f)
        help_priorities[cmd.name] = help_priority
        return cmd
    return decorator

def get_command(self, ctx, cmd_name):
    rv = click.Group.get_command(self, ctx, cmd_name)
    if rv is not None:
        return rv
    sim_commands = most_sim_com(cmd_name, COMMANDS)

    matches = [cmd for cmd in self.list_commands(ctx) if cmd in sim_commands]
    if not matches:
        ctx.fail(click.style('Unknown command and no similar command was found!', fg='red'))
    elif len(matches) == 1:
        click.echo(click.style(f'Unknown command! Will use best match {matches[0]}.', fg='red'))
        return click.Group.get_command(self, ctx, matches[0])
    ctx.fail(click.style(f'Unknown command. Most similar commands were {", ".join(sorted(matches))}', fg='red'))

1 Ответ

1 голос
/ 28 апреля 2020

Это первый черновик и самое наивное решение, которое я могу придумать, поэтому оно может изменить его, если не решит полностью вашу проблему. Поменяет ли ваш код на что-то вроде этой справки?

@click.group(cls=MyGroup)
def myapp():
    pass

@myapp.command()
@click.argument('myarg',type=str, required=False)
def mycommand(myarg: str=None) -> None:
    validate_my_command(myarg) # this is where you do your custom logic and error message handling

Преимущество такого способа состоит в том, что он явный и поддерживается в соответствии с предлагаемым Click предложенным способом сделать это. Однако, если вы хотите сделать это для каждой команды, мы можем рассмотреть более сложные подходы

Дайте мне знать, что вы думаете

...