AFAICT, это невозможно с Click. Документы утверждают, что:
Щелчок строго разделяет параметры между командами и подкомандами.
Это означает, что параметры и аргументы для конкретной команды
должны быть указаны после самого имени команды, но перед любым
другие названия команд.
Возможный обходной путь - написание common_options
декоратора. В следующем примере используется тот факт, что click.option
- это функция, которая возвращает функцию декоратора, которая должна быть применена последовательно. IOW, следующее:
@click.option("-a")
@click.option("-b")
def hello(a, b):
pass
эквивалентно следующему:
def hello(a, b):
pass
hello = click.option("-a")(click.option("-b")(hello))
Недостатком является то, что вам нужно установить общий аргумент для всех ваших подкоманд. Это может быть решено с помощью **kwargs
, который собирает аргументы ключевых слов в виде слова.
(С другой стороны, вы могли бы написать более продвинутый декоратор, который бы передавал аргументы в контекст или что-то в этом роде, но моя простая попытка не сработала, и я не готов попробовать более продвинутые подходы. Я мог бы отредактировать ответьте позже и добавьте их.)
С этим мы можем сделать программу:
import click
import functools
@click.group()
def cli():
pass
def common_options(f):
options = [
click.option("-a", is_flag=True),
click.option("-b", is_flag=True),
]
return functools.reduce(lambda x, opt: opt(x), options, f)
@cli.command()
@common_options
def hello(**kwargs):
print(kwargs)
# to get the value of b:
print(kwargs["b"])
@cli.command()
@common_options
@click.option("-c", "--citrus")
def world(citrus, a, **kwargs):
print("citrus is", citrus)
if a:
print(kwargs)
else:
print("a was not passed")
if __name__ == "__main__":
cli()