python中的互斥选项组单击

Bry*_*yce 18 python python-click

如何在Click中创建互斥选项组?我想要接受标志"--all"或者使用像"--color red"这样的参数选项.

Jac*_*cob 26

我最近遇到了同样的用例; 这就是我想出来的.对于每个选项,您可以提供冲突选项列表.

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
        )
Run Code Online (Sandbox Code Playgroud)

然后使用常规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() 
Run Code Online (Sandbox Code Playgroud)

这是一个 包含上面代码的要点,并显示运行它的输出.

如果这对你不起作用,还有一些(封闭的)问题在click github页面上提到这个问题,你可以使用一些想法.


sbo*_*oby 12

您可以使用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)
Run Code Online (Sandbox Code Playgroud)

帮助将是:

Usage: cmd [OPTIONS]

Color options [mutually exclusive]:
  --all       
  --color TEXT

Other options:
  --help        Show this message and exit.
Run Code Online (Sandbox Code Playgroud)

选项 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)
Run Code Online (Sandbox Code Playgroud)

以这种方式定义的约束可以记录在命令帮助中!默认情况下禁用此功能,但可以轻松启用传递show_constraints=True@command. 结果:

Usage: cmd [OPTIONS]

Options:
  --all       
  --color TEXT
  --help        Show this message and exit.

Constraints:
  {--all, --color}  mutually exclusive
Run Code Online (Sandbox Code Playgroud)

更新:现在可以使用约束作为装饰器,而不是使用@contraint

@command()
@mutually_exclusive(
    option('--all', 'all_colors', is_flag=True),
    option('--color'),
)
def cmd(**kwargs):
    print(kwargs)
Run Code Online (Sandbox Code Playgroud)

错误信息

在这两种情况下,如果您运行cmd --all --color red,您将得到:

Usage: cmd [OPTIONS]
Try 'cmd --help' for help.

Error: the following parameters are mutually exclusive:
  --all 
  --color
Run Code Online (Sandbox Code Playgroud)

其他限制

Cloup 定义的约束应该可以满足您 99.9% 的需求。它甚至支持条件约束!

例如,如果用户必须提供互斥选项之一,请在上例中替换mutually_exclusive为。RequireExactly(1)

您可以在此处找到所有可用的约束。


iro*_*oln 11

您可以使用以下软件包: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()
Run Code Online (Sandbox Code Playgroud)

应用帮助:

$ app.py --help
Usage: app.py [OPTIONS]

Options:
  Grouped options: [mutually_exclusive, required]
                                  Group description
    --all
    --color TEXT
  --help                          Show this message and exit.
Run Code Online (Sandbox Code Playgroud)