合并 cloup.group 和 click-default-group

Combine cloup.group and click-default-group

我正在为我的 CLI 使用 cloup 的约束功能。

我有一些没有共同参数的命令 a 和 b。

import cloup


@cloup.group()
def cli():
    pass

@cli.command(show_constraints=True)
@cloup.option("--foo")
def a(**kwargs):
    print("hello")

@cli.command(show_constraints=True)
@cloup.option("--bar")
def b():
    pass

cli()

我希望 a 成为默认命令。所以,我想要以下输出:

$ python3 main.py 
Usage: main.py [OPTIONS] COMMAND [ARGS]...

Options:
  --help  Show this message and exit.

Commands:
  a
  b

$ python3 main.py a --foo hey
hello

到目前为止,这按预期工作。现在我还希望 a 成为默认命令,因此我想看到:

$ python3 main.py --foo hey
hello

我知道我可以在 cli 中有如下行为:

@cloup.group(invoke_without_command=True)
def cli():
    print("custom behaviour")

那会给

$ python3 main.py
custom behaviour

我以为我可以在cli函数中将调用转发给a,但是组cli不知道命令[=]的选项--foo 20=]:

$ python3 main.py --foo hey
Usage: main.py [OPTIONS] COMMAND [ARGS]...
Try 'main.py --help' for help.

Error: No such option: --foo

我被困在这里了。我在这里找到了问题的答案 (),但我必须使用 cloup.group。所以如果我在那里应用解决方案...

@cloup.group(cls=DefaultGroup, default='a',default_if_no_args=True)
def cli():
    pass

...我会得到

Traceback (most recent call last):
  File "main.py", line 11, in <module>
    @cloup.option("--foo")
  File "<SNIP>/.venv_3.6.9/lib/python3.6/site-packages/click/core.py", line 1834, in decorator
    cmd = command(*args, **kwargs)(f)
  File "<SNIP>/.venv_3.6.9/lib/python3.6/site-packages/click/decorators.py", line 184, in decorator
    cmd = _make_command(f, name, attrs, cls)  # type: ignore
  File "<SNIP>/.venv_3.6.9/lib/python3.6/site-packages/click/decorators.py", line 152, in _make_command
    **attrs,
TypeError: __init__() got an unexpected keyword argument 'show_constraints'

这只是矛尖 - cloup.group 中的任何其他功能也将不可用。

我想可以合并 cloupclick-default-groupgroup,但这看起来非常耗时。有没有更简单的方法来获取 cloup 中的默认命令?

我也找到了https://click.palletsprojects.com/en/8.0.x/api/?highlight=group#click.Context.ignore_unknown_options。但是如果我理解正确的话,只有 commands 有上下文而 groups 没有,所以它没有帮助。

这里是 Cloup 的作者。你可以试试这个:

"""
This example requires click-default-group.
"""
import cloup
from click import Context, HelpFormatter
from click_default_group import DefaultGroup


class GroupWithDefaultCommand(cloup.Group, DefaultGroup):
    # Optional: mark default command with "*"
    def format_subcommand_name(
        self, ctx: click.Context, name: str, cmd: click.Command
    ) -> str:
        if name == self.default_cmd_name:
            name = name + "*"
        return super().format_subcommand_name(ctx, name, cmd)


@cloup.group(cls=GroupWithDefaultCommand, default='alice')
def cli():
    pass


@cli.command()
@cloup.option("--foo")
def alice(**kwargs):
    print("Called alice with", kwargs)


@cli.command()
@cloup.option("--bar")
def bob(**kwargs):
    print("Called bob with", kwargs)


if __name__ == '__main__':
    cli()

AFAICS 现在,您只会丢失针对错误输入命令(来自 Cloup)的“您是不是要输入”建议和指示默认命令的“*”(来自 click-default-group)(使用 Cloup 引入的方法 Group.format_subcommand_name 实际上很容易实现)。如果您发现任何其他问题,请告诉我。如果它运行良好,我可能会将它添加到示例文件夹中。

尽管如此,我建议您根本不要使用默认命令。在 click-default-group 问题跟踪器中,您可以看到它与 click-help-colors 和 click-repl 冲突。因此,除非您不害怕修复可能因使用默认命令而可能出现的问题,否则请不要使用默认命令。作为替代方案,您可以只建议您的用户为默认命令定义一个别名(例如,通过使用 alias unix 命令)。