gpt4 book ai didi

python - 命令链的别名

转载 作者:太空狗 更新时间:2023-10-29 22:24:37 26 4
gpt4 key购买 nike

我有一个带有命令的工具:step1step2step3

我可以通过调用链接它们:

$工具step1 step2 step3

我想要一个名为 all 的别名来运行所有步骤,方法是调用:

$工具全部

我找到了一个可行的解决方案,但它似乎不适合我,因为在后台调用了两次 cli():

@click.group(chain=True)
def cli():
print('cli() has been called')

...

@cli.command()
def all():
cli(args=['step1', 'step2', 'step3'])

在没有调用 cli() 两次的副作用的情况下,如何做到这一点?

最佳答案

提供一些别名的一种方法是拦截命令并直接操作args 列表。这可以通过自定义类来完成,例如:

自定义类

此类重写 click.Group.__call__() 方法以允许在调用命令处理器之前编辑 args 列表。此外,它会覆盖 format_epilog 以添加别名的帮助文档。

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 类可以执行别名扩张。

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 并覆盖所需的方法是一件相对容易的事情。

通过覆盖 __call__ 方法,我们可以拦截所有命令调用。然后,如果 args 列表以已知别名开头,我们通过删除该别名命令并将其替换为别名来编辑 args 列表。

通过覆盖 format_epilog 方法,我们可以为别名添加帮助文档。

测试代码:

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

关于python - 命令链的别名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47983367/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com