Обязательные параметры приложения щелчка Python имеют приоритет над параметром справки подкоманды - PullRequest
1 голос
/ 23 апреля 2019

Я создаю приложение click 7.x с Python 3.6 , и у меня возникают проблемы с получением помощи при работе с подкомандами.У меня есть глобальная опция, которая обязательна, и эта опция сообщается как отсутствующая, когда я запускаю справку для любой подкоманды.

Например, учитывая следующий фиктивный скрипт cli.py:

import click


@click.group()
@click.option('--directory', required=True)
def cli(directory):
    """
    this is a tool that has an add and remove command
    """
    click.echo(directory)


@cli.command()
@click.overwrite('--overwrite', is_flag=True)
def add(overwrite):
    """
    this is the add command
    """
    click.echo("add overwrite={}".format(overwrite))


@cli.command()
def remove():
    """
    this is the remove command
    """
    click.echo('remove')


if __name__ == '__main__':
    cli()

Когда я запускаю следующее:

python cli.py --help

Я получаю желаемый результат:

Usage cli.py [OPTIONS] COMMAND [ARGS]...

  this is a tool that has an add and remove command

Options:
  --directory TEXT  [required]
  --help            Show this message and exit.

Commands:
  add     this is the add command
  remove  this is the remove command

Но если я запускаю это:

python cli.py add --help

Я получаюследующая ошибка:

Usage cli.py [OPTIONS] COMMAND [ARGS]...
Try "cli.py --help" for help.

Error: Missing option "--directory"

Как получить справку для команды add, отображаемой без указания опции --directory?

1 Ответ

1 голос
/ 24 апреля 2019

Вы можете использовать пользовательский класс click.Group, чтобы игнорировать требуемые аргументы при запросе --help, например:

Пользовательский класс:

class IgnoreRequiredWithHelp(click.Group):
    def parse_args(self, ctx, args):
        try:
            return super(IgnoreRequiredWithHelp, self).parse_args(ctx, args)
        except click.MissingParameter as exc:
            if '--help' not in args:
                raise

            # remove the required params so that help can display
            for param in self.params:
                param.required = False
            return super(IgnoreRequiredWithHelp, self).parse_args(ctx, args)

Использование пользовательского класса:

Чтобы использовать пользовательский класс, передайте его в качестве аргумента cls декоратору группы, например:

@click.group(cls=IgnoreRequiredWithHelp)
....
def my_group():
    ....

Как это работает?

Это работает, потому что click - это хорошо спроектированная OO-инфраструктура. Декоратор @click.group() обычно создает экземпляр объекта click.Group, но позволяет переопределить это поведение параметром cls. Так что сравнительно легко унаследовать от click.Group в нашем собственном классе и переопределить нужные методы.

В этом случае мы переходим click.Group.parse_args() и ловим исключение click.MissingParameter. Затем мы отменяем атрибут required во всех параметрах и повторяем анализ.

Тестовый код:

import click

@click.group(cls=IgnoreRequiredWithHelp)
@click.option('--directory', required=True)
def cli(directory):
    """
    this is a tool that has an add and remove command
    """
    click.echo(directory)

@cli.command()
@click.option('--overwrite', is_flag=True)
def add(overwrite):
    """
    this is the add command
    """
    click.echo("add overwrite={}".format(overwrite))


@cli.command()
def remove():
    """
    this is the remove command
    """
    click.echo('remove')


if __name__ == "__main__":
    commands = (
        'add --help',
        '--help',
        '--directory a_dir add'
        '',
    )

    import sys, time

    time.sleep(1)
    print('Click Version: {}'.format(click.__version__))
    print('Python Version: {}'.format(sys.version))
    for cmd in commands:
        try:
            time.sleep(0.1)
            print('-----------')
            print('> ' + cmd)
            time.sleep(0.1)
            cli(cmd.split())

        except BaseException as exc:
            if str(exc) != '0' and \
                    not isinstance(exc, (click.ClickException, SystemExit)):
                raise

Результаты:

Click Version: 6.7
Python Version: 3.6.3 (v3.6.3:2c5fed8, Oct  3 2017, 18:11:49) [MSC v.1900 64 bit (AMD64)]
-----------
> add --help

Usage: test.py add [OPTIONS]

  this is the add command

Options:
  --overwrite
  --help       Show this message and exit.
-----------
> --help
Usage: test.py [OPTIONS] COMMAND [ARGS]...

  this is a tool that has an add and remove command

Options:
  --directory TEXT
  --help            Show this message and exit.

Commands:
  add     this is the add command
  remove  this is the remove command
-----------
> --directory a_dir add
a_dir
add overwrite=False
...