可以用 Python Click 做这样的事情吗?
@click.command(name=['my-command', 'my-cmd'])
def my_command():
pass
我希望我的命令行是这样的:
mycli my-command
和
mycli my-cmd
但引用相同的函数。
我需要上像AliasedGroup这样的课程吗?
AliasedGroup 不是您想要的,因为它允许最短的前缀匹配,而且您似乎需要实际的别名。但这个例子确实提供了可行的方向的提示。它继承自
click.Group
并覆盖了一些行为。
这是实现您所追求的目标的一种方法:
该类覆盖了用于装饰命令函数的
click.Group.command()
方法。它增加了传递命令别名列表的能力。此类还添加了引用别名命令的简短帮助。
class CustomMultiCommand(click.Group):
def command(self, *args, **kwargs):
"""Behaves the same as `click.Group.command()` except if passed
a list of names, all after the first will be aliases for the first.
"""
def decorator(f):
if isinstance(args[0], list):
_args = [args[0][0]] + list(args[1:])
for alias in args[0][1:]:
cmd = super(CustomMultiCommand, self).command(
alias, *args[1:], **kwargs)(f)
cmd.short_help = "Alias for '{}'".format(_args[0])
else:
_args = args
cmd = super(CustomMultiCommand, self).command(
*_args, **kwargs)(f)
return cmd
return decorator
通过将
cls
参数传递给 click.group()
装饰器,通过 group.command()
添加到组的任何命令都可以传递命令名称列表。
@click.group(cls=CustomMultiCommand)
def cli():
"""My Excellent CLI"""
@cli.command(['my-command', 'my-cmd'])
def my_command():
....
import click
@click.group(cls=CustomMultiCommand)
def cli():
"""My Excellent CLI"""
@cli.command(['my-command', 'my-cmd'])
def my_command():
"""This is my command"""
print('Running the command')
if __name__ == '__main__':
cli('--help'.split())
Usage: my_cli [OPTIONS] COMMAND [ARGS]...
My Excellent CLI
Options:
--help Show this message and exit.
Commands:
my-cmd Alias for 'my-command'
my-command This is my command
这里有一个更简单的方法来解决同样的问题:
class AliasedGroup(click.Group):
def get_command(self, ctx, cmd_name):
try:
cmd_name = ALIASES[cmd_name].name
except KeyError:
pass
return super().get_command(ctx, cmd_name)
@click.command(cls=AliasedGroup)
def cli():
...
@click.command()
def install():
...
@click.command()
def remove():
....
cli.add_command(install)
cli.add_command(remove)
ALIASES = {
"it": install,
"rm": remove,
}
click-aliases
库。
它的工作方式有点像其他答案,只是你不必自己声明命令类:
import click
from click_aliases import ClickAliasedGroup
@click.group(cls=ClickAliasedGroup)
def cli():
pass
@cli.command(aliases=['my-cmd'])
def my_command():
pass
我尝试了@Stephan Rauch 的解决方案,并遇到了一些挑战,例如帮助文本输出,因此我对其进行了扩展。这是在我看到有一个用于此目的的库之前,所以我还没有尝试过,因为我构建的内容正在按照我想要的方式工作。
从基本命令复制帮助信息时向命令添加
aliases=['foo', 'bar']
参数。
class CustomCliGroup(click.Group):
"""Custom Cli Group for Click"""
def command(self, *args, **kwargs):
"""Adds the ability to add `aliases` to commands."""
def decorator(f):
aliases = kwargs.pop("aliases", None)
if aliases and isinstance(aliases, list):
name = kwargs.pop("name", None)
if not name:
raise click.UsageError("`name` command argument is required when using aliases.")
base_command = super(CustomCliGroup, self).command(
name, *args, **kwargs
)(f)
for alias in aliases:
cmd = super(CustomCliGroup, self).command(alias, *args, **kwargs)(f)
cmd.help = f"Alias for '{name}'.\n\n{cmd.help}"
cmd.params = base_command.params
else:
cmd = super(CustomCliGroup, self).command(*args, **kwargs)(f)
return cmd
return decorator
import click
@click.group(
context_settings=dict(help_option_names=["-h", "--help"]), cls=CustomCliGroup
)
def cli():
"""My Excellent CLI"""
@cli.command()
def hello():
"""Says hello"""
click.echo("Hello, World!")
@cli.command(name="do", aliases=["stuff"])
@click.argument("name")
@click.option("--times", "-t", default=1, help="Number of times to do the thing")
def my_command(name, times):
"""This is my command"""
click.echo(f"Doing {name} {times} times.")
if __name__ == "__main__":
cli()
> python test.py -h
Usage: test.py [OPTIONS] COMMAND [ARGS]...
My Excellent CLI
Options:
-h, --help Show this message and exit.
Commands:
do This is my command
hello Says hello
stuff Alias for 'do'.
------------------------
> python test.py do -h
Usage: test.py do [OPTIONS] NAME
This is my command
Options:
-t, --times INTEGER Number of times to do the thing
-h, --help Show this message and exit.
------------------------
> python test.py stuff -h
Usage: test.py stuff [OPTIONS] NAME
Alias for 'do'.
This is my command
Options:
-t, --times INTEGER Number of times to do the thing
-h, --help Show this message and exit.