结合 cloup.group 和 click-default-group

发布于 2025-01-12 08:42:17 字数 2637 浏览 2 评论 0原文

我在 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<命令a的/code>:

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

Error: No such option: --foo

我被困在这里了。我在这里找到了问题的答案(A command without name, in Click ),但我必须使用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。但如果我理解正确的话,只有命令有上下文,组没有,所以它没有帮助。

I'm using cloup for my CLI for its constraints feature.

I have some commands a and b which have no common arguments.

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()

I want a to be the default command. So, I'd like the following output:

$ 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

So far, this works as expected. Now I also want a to be the default command, thus I'd like to see:

$ python3 main.py --foo hey
hello

I know that I can have behaviour in cli as follows:

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

That will give

$ python3 main.py
custom behaviour

I thought that I could forward the call to a in the cli function, but the group cli does not know the option --foo of command a:

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

Error: No such option: --foo

I'm stuck here. I found an answer to the question here (A command without name, in Click), but I have to use cloup.group. So if I applied the solution there ...

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

... I'd get

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'

And that's only the tip of the spear - any other features from cloup.group also become unavailable.

I guess one could merge the groups of cloup and click-default-group, but that looks horribly time-consuming. Is there an easier way to get a default command in cloup?

I also found https://click.palletsprojects.com/en/8.0.x/api/?highlight=group#click.Context.ignore_unknown_options. But if I understood correctly, only commands have a context and groups do not, so it wouldn't help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

深巷少女 2025-01-19 08:42:17

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 命令)。

Author of Cloup here. You can try this:

"""
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 now, you'll only lose the "Did you mean" suggestion for mistyped commands (from Cloup) and the "*" indicating the dafault command (from click-default-group) (it was actually pretty easy to implement that with the method Group.format_subcommand_name introduced by Cloup). Let me know if you find any other problems. If it works well, I'll maybe add it to the examples folder.

Nonetheless, I'd suggest you to not use a default command at all. In click-default-group issue tracker, you can see it conflicts with click-help-colors and click-repl. So, unless you're not afraid of fixing issue that may potentially arise from having a default command, don't have one. As an alternative, you can just suggest your users to define an alias for the default command (e.g. by using the alias unix command).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文