Как указать значение по умолчанию для списка аргументов, обрабатываемых кликом? - PullRequest
1 голос
/ 29 мая 2019

У меня есть эта строка кода, которая должна захватить все имена файлов, переданные моему скрипту Python:

@click.argument("logs", nargs=-1, type=click.File('r'), required=1)

Когда имена файлов не передаются, я хочу по умолчанию -, чтоесть, стандартный ввод.Итак, если я попытаюсь:

@click.argument("logs", nargs=-1, type=click.File('r'), required=1, default="-")

, щелчок станет недовольным и выдаст эту ошибку:

TypeError: nargs = -1 в сочетании со значением по умолчанию не поддерживается.

Есть ли обходной путь для этого?Я попытался установить nargs=0, но это выдает другую ошибку:

IndexError: индекс кортежа вне диапазона

Ответы [ 3 ]

2 голосов
/ 29 мая 2019

По умолчанию stdin для потенциально пустого списка файлов, вы можете определить пользовательский класс аргумента, например:

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

class FilesDefaultToStdin(click.Argument):
    def __init__(self, *args, **kwargs):
        kwargs['nargs'] = -1
        kwargs['type'] = click.File('r')
        super().__init__(*args, **kwargs)

    def full_process_value(self, ctx, value):
        return super().process_value(ctx, value or ('-', ))

Определение этого поведения как классаобеспечивает простое повторное использование.

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

@click.command()
@click.argument("logs", cls=FilesDefaultToStdin)
def main(logs):
    ...

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

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

В этом случае мы переопределяем click.Argument.full_process_value().В нашем full_process_value() мы ищем пустой список аргументов, и если он пустой, мы добавляем в список аргумент - (stdin).

Кроме того, мы автоматически назначаем nargs=-1 и type=click.File('r') аргументов.

1 голос
/ 29 мая 2019

Поскольку click прямо заявили, что они отключили эту особенность, необходимую для этого вопроса, как сообщалось в об этой проблеме в их проекте, потребуется обходной путь, который может быть легко реализован как частьфункция Python (вместо некоторого дополнительного количества кода на bash, как предлагается в комментарии к другому ответу).

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

import sys
import click

@click.command()
@click.argument("logs", nargs=-1, type=click.File('r'))
def main(logs):
    if not logs:
        logs = (sys.stdin,)
    print(logs)
    # do stuff with logs

if __name__ == '__main__': 
    main()

Пример выполнения

$ python fail.py 
(<_io.TextIOWrapper name='<stdin>' mode='r' encoding='UTF-8'>,)
$ python fail.py -
(<_io.TextIOWrapper name='<stdin>' mode='r' encoding='UTF-8'>,)
$ python fail.py foo bar
(<_io.TextIOWrapper name='foo' mode='r' encoding='UTF-8'>, <_io.TextIOWrapper name='bar' mode='r' encoding='UTF-8'>)
0 голосов
/ 29 мая 2019

Следующий код:

import click


@click.command()
@click.option('--logs', '-l', multiple=True, default='-')
def cli(logs):
    click.echo('\n'.join(logs))

Будет выдавать следующее:

$ myhello -l foo.log -l bar.log -l baz.log
foo.log
bar.log
baz.log
$ myhello
-

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...