一连串命令的别名 [英] Alias for a chain of commands
问题描述
我有一个 tool
,其中包含以下命令: step1
, step2
和 step3
.
I have a tool
with commands: step1
, step2
and step3
.
我可以通过以下方式链接它们:
I can chain them by calling:
$工具step1 step2 step3
我想要一个名为 all
的别名,以通过调用以下命令来运行所有步骤:
I would like to have an alias named all
to run all the steps by calling:
$工具全部
我找到了一个可行的解决方案,但由于在后台调用了两次 cli()
,这对我来说似乎不合适:
I have found a solution that works but it doesn't seem right for me because of calling cli()
twice under the hood:
@click.group(chain=True)
def cli():
print('cli() has been called')
...
@cli.command()
def all():
cli(args=['step1', 'step2', 'step3'])
在没有两次调用 cli()
的副作用的情况下,该怎么办呢?
How else could this be done without the side effect of calling cli()
twice?
推荐答案
提供一些别名的一种方法是拦截命令并直接操作 args
列表.可以使用以下自定义类完成此操作:
One way to provide some aliases is to intercept the command and directly manipulate the args
list. That can be done with a custom class like:
此类重写 click.Group .__ call __()
方法,以允许在调用命令处理器之前编辑 args
列表.此外,它会覆盖 format_epilog
来添加别名的帮助文档.
This class overrides the click.Group.__call__()
method to allow editing the args
list before calling the command processor. In addition it overrides format_epilog
to add help documentation for the aliases.
class ExpandAliasesGroup(click.Group):
def __init__(self, *args, **kwargs):
self.aliases = kwargs.pop('aliases', {})
super(ExpandAliasesGroup, self).__init__(*args, **kwargs)
def __call__(self, *args, **kwargs):
if args and args[0] and args[0][0] in self.aliases:
alias = self.aliases[args[0][0]]
args[0].pop(0)
for command in reversed(alias):
args[0].insert(0, command)
return super(ExpandAliasesGroup, self).__call__(*args, **kwargs)
@property
def alias_help(self):
return '\n'.join(
'{}: {}'.format(alias, ' '.join(commands))
for alias, commands in sorted(self.aliases.items())
)
def format_epilog(self, ctx, formatter):
"""Inject our aliases into the help string"""
if self.aliases:
formatter.write_paragraph()
formatter.write_text('Aliases:')
with formatter.indentation():
formatter.write_text(self.alias_help)
# call the original epilog
super(ExpandAliasesGroup, self).format_epilog(ctx, formatter)
使用自定义类
通过将 cls
参数和别名字典传递给 click.group()
装饰器, ExpandAliasesGroup
类可以执行别名扩展.
Using the Custom Class
By passing the cls
parameter, and a dict of aliases to the click.group()
decorator, the ExpandAliasesGroup
class can do alias expansion.
aliases = dict(all='command1 command2 command3'.split())
@click.group(chain=True, cls=ExpandAliasesGroup, aliases=aliases)
def cli():
....
这是如何工作的?
之所以有用,是因为click是一个设计良好的OO框架. @ click.group()
装饰器通常会实例化 click.Group
对象,但允许使用 cls
参数覆盖此行为.因此,从我们自己的类中的 click.Group
继承并覆盖所需的方法是相对容易的事情.
How does this work?
This works because click is a well designed OO framework. The @click.group()
decorator usually instantiates a click.Group
object but allows this behavior to be over ridden with the cls
parameter. So it is a relatively easy matter to inherit from click.Group
in our own class and over ride the desired methods.
通过覆盖 __ call __
方法,我们可以拦截所有命令调用.然后,如果args列表以已知的别名开头,我们将通过删除该别名命令并将其替换为别名来编辑args列表.
By overriding the __call__
method we can intercept all command calls. Then if the list of args starts with a known alias, we edit the args list by removing that aliased command and replacing it with the aliases.
通过覆盖 format_epilog
方法,我们可以为别名添加帮助文档.
By overriding the format_epilog
method we can add help documentation for the aliases.
import click
aliases = dict(all='command1 command2 command3'.split())
@click.group(cls=ExpandAliasesGroup, chain=True, aliases=aliases)
def cli():
pass
@cli.command()
def command1():
click.echo('Command 1')
@cli.command()
def command2():
click.echo('Command 2')
@cli.command()
def command3():
click.echo('Command 3')
if __name__ == "__main__":
commands = (
'command1',
'command3',
'command1 command2',
'all',
'--help',
)
for cmd in commands:
try:
print('-----------')
print('> ' + cmd)
cli(cmd.split())
except:
pass
测试结果:
-----------
> command1
Command 1
-----------
> command3
Command 3
-----------
> command1 command2
Command 1
Command 2
-----------
> all
Command 1
Command 2
Command 3
-----------
> --help
Usage: test.py [OPTIONS] COMMAND1 [ARGS]... [COMMAND2 [ARGS]...]...
Options:
--help Show this message and exit.
Commands:
command1 Command #1 comes first
command2 Command #2 is after command #1
command3 Command #3 saves the best for last
Aliases:
all: command1 command2 command3
这篇关于一连串命令的别名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!