Как я могу создать взаимоисключающую группу опций в Click? Я хочу либо принять флаг «--all», либо выбрать опцию с параметром, например «--color red».
Взаимоисключающие группы опций в python Click
Ответы (3)
Недавно я столкнулся с этим же вариантом использования; это то, что я придумал. Для каждого варианта можно дать список конфликтующих вариантов.
from click import command, option, Option, UsageError
class MutuallyExclusiveOption(Option):
def __init__(self, *args, **kwargs):
self.mutually_exclusive = set(kwargs.pop('mutually_exclusive', []))
help = kwargs.get('help', '')
if self.mutually_exclusive:
ex_str = ', '.join(self.mutually_exclusive)
kwargs['help'] = help + (
' NOTE: This argument is mutually exclusive with '
' arguments: [' + ex_str + '].'
)
super(MutuallyExclusiveOption, self).__init__(*args, **kwargs)
def handle_parse_result(self, ctx, opts, args):
if self.mutually_exclusive.intersection(opts) and self.name in opts:
raise UsageError(
"Illegal usage: `{}` is mutually exclusive with "
"arguments `{}`.".format(
self.name,
', '.join(self.mutually_exclusive)
)
)
return super(MutuallyExclusiveOption, self).handle_parse_result(
ctx,
opts,
args
)
Затем используйте обычный декоратор option
, но передайте аргумент cls
:
@command(help="Run the command.")
@option('--jar-file', cls=MutuallyExclusiveOption,
help="The jar file the topology lives in.",
mutually_exclusive=["other_arg"])
@option('--other-arg',
cls=MutuallyExclusiveOption,
help="The jar file the topology lives in.",
mutually_exclusive=["jar_file"])
def cli(jar_file, other_arg):
print "Running cli."
print "jar-file: {}".format(jar_file)
print "other-arg: {}".format(other_arg)
if __name__ == '__main__':
cli()
Вот суть, которая включает приведенный выше код и показывает результат его выполнения.
Если это не сработает для вас, есть несколько (закрытых) проблем, упоминающих об этом на странице click github с парой идей, которые вы можете использовать.
Вы можете использовать следующий пакет: https://github.com/espdev/click-option-group< /а>
import click
from click_option_group import optgroup, RequiredMutuallyExclusiveOptionGroup
@click.command()
@optgroup.group('Grouped options', cls=RequiredMutuallyExclusiveOptionGroup,
help='Group description')
@optgroup.option('--all', 'all_', is_flag=True, default=False)
@optgroup.option('--color')
def cli(all_, color):
print(all_, color)
if __name__ == '__main__':
cli()
помощь приложения:
$ app.py --help
Usage: app.py [OPTIONS]
Options:
Grouped options: [mutually_exclusive, required]
Group description
--all
--color TEXT
--help Show this message and exit.
Вы можете использовать Cloup, пакет, который добавляет группы опций и ограничения в Click. У вас есть два варианта решения этой проблемы в Cloup.
Отказ от ответственности: я являюсь автором пакета.
Вариант 1: @option_group
Когда вы определяете группу параметров с помощью @option_group
, параметры каждой группы отображаются в отдельных разделах справки (например, в argparse). Вы можете применять ограничения (например, mutually_exclusive
) к группам опций следующим образом:
from cloup import command, option, option_group
from cloup.constraints import mutually_exclusive
@command()
@option_group(
'Color options',
option('--all', 'all_colors', is_flag=True),
option('--color'),
constraint=mutually_exclusive
)
def cmd(**kwargs):
print(kwargs)
Помощь будет:
Usage: cmd [OPTIONS]
Color options [mutually exclusive]:
--all
--color TEXT
Other options:
--help Show this message and exit.
Вариант 2: @ограничение
Если вы не хотите, чтобы группы параметров отображались в справке по команде, вы можете использовать @constraint
и указать ограниченные параметры по их (целевому) имени:
from cloup import command, option
from cloup.constraints import constraint, mutually_exclusive
@command()
@option('--all', 'all_colors', is_flag=True)
@option('--color')
@constraint(mutually_exclusive, ['all_colors', 'color'])
def cmd(**kwargs):
print(kwargs)
Определенные таким образом ограничения можно задокументировать в справке по команде! Эта функция отключена по умолчанию, но ее можно легко включить, передав show_constraints=True
в @command
. Результат:
Usage: cmd [OPTIONS]
Options:
--all
--color TEXT
--help Show this message and exit.
Constraints:
{--all, --color} mutually exclusive
Сообщение об ошибке
В обоих случаях, если вы запустите cmd --all --color red
, вы получите:
Usage: cmd [OPTIONS]
Try 'cmd --help' for help.
Error: the following parameters are mutually exclusive:
--all
--color
Другие ограничения
Cloup определяет ограничения, которые должны покрывать 99,9% ваших потребностей. Он даже поддерживает условные ограничения!
Например, если пользователь должен предоставить один из ваших взаимоисключающих вариантов, замените mutually_exclusive
на RequireExactly(1)
в приведенном выше примере.
Все доступные ограничения можно найти здесь.