是否可以在click.option
上设置click.group
,但在整个命令的末尾传递选项?
@click.option(
'-d', '--debug',
help="change to debug mode")
@click.group()
def cli(ctx, **kwargs):
"""
help message
"""
@click.command()
def version():
"""
version
"""
pass
所需的命令如下所示:
./cli.py version -d
但这失败了:
错误:没有这样的选项:-d
答案 0 :(得分:0)
在click.option
上设置click.group
但在整个命令的末尾传递选项的一种方法是从click.Group
继承,并自定义调用命令的代码
这个问题得到了部分回答here。从该问题我们将使用自定义类:GroupWithCommandOptions
。
import click
class GroupWithCommandOptions(click.Group):
""" Allow application of options to group with multi command """
def add_command(self, cmd, name=None):
click.Group.add_command(self, cmd, name=name)
# add the group parameters to the command
for param in self.params:
cmd.params.append(param)
# hook the commands invoke with our own
cmd.invoke = self.build_command_invoke(cmd.invoke)
self.invoke_without_command = True
def build_command_invoke(self, original_invoke):
def command_invoke(ctx):
""" insert invocation of group function """
# separate the group parameters
ctx.obj = dict(_params=dict())
for param in self.params:
name = param.name
ctx.obj['_params'][name] = ctx.params[name]
del ctx.params[name]
# call the group function with its parameters
params = ctx.params
ctx.params = ctx.obj['_params']
self.invoke(ctx)
ctx.params = params
# now call the original invoke (the command)
original_invoke(ctx)
return command_invoke
要使用自定义类,请将cls
参数传递给@click.group()
装饰者喜欢:
@click.group(cls=GroupWithCommandOptions)
然后使用群组
创建click.CommandCollection
cli = click.CommandCollection(sources=[group1])
命令集很重要,因为我们需要控制何时调用组,以及
CommandCollection
不会调用他们的小组,因此我们可以在适当的时候自行完成。
这是有效的,因为click是一个设计良好的OO框架。该
@click.group()
装饰器通常实例化一个
click.Group
对象但允许此行为被覆盖
使用cls
参数。所以这是一个相对的
很容易在我们自己的班级继承click.Group
并过度使用所需的方法。
在这种情况下,我们过度click.Group.add_command()
将组参数添加到命令中
然后猴子修补命令的invoke()
方法,这样可以在命令调用之前调用组调用以允许
它处理在命令中指定的选项。
@click.group(cls=GroupWithCommandOptions)
@click.option('-d', '--debug', help="change to debug mode", is_flag=True)
def group1(**kwargs):
"""Our great program"""
click.echo('debug: %s' % kwargs['debug'])
@group1.command()
@click.pass_context
def version(ctx):
"""Show the Version"""
click.echo('show version here')
cli = click.CommandCollection(sources=[group1])
if __name__ == "__main__":
commands = (
'version -d',
'-d version',
'version',
'--help',
'version --help',
)
import sys, time
time.sleep(1)
print('Click Version: {}'.format(click.__version__))
print('Python Version: {}'.format(sys.version))
for cmd in commands:
try:
time.sleep(0.1)
print('-----------')
print('> ' + cmd)
time.sleep(0.1)
cli(cmd.split())
except BaseException as exc:
if str(exc) != '0' and \
not isinstance(exc, (click.ClickException, SystemExit)):
raise
Click Version: 6.7
Python Version: 3.6.2 (default, Jul 17 2017, 23:14:31)
[GCC 5.4.0 20160609]
-----------
> version -d
debug: True
show version here
-----------
> -d version
Error: no such option: -d
-----------
> version
debug: False
show version here
-----------
> --help
Usage: test.py [OPTIONS] COMMAND [ARGS]...
Options:
--help Show this message and exit.
Commands:
version Show the Version
-----------
> version --help
Usage: test.py version [OPTIONS]
Show the Version
Options:
-d, --debug change to debug mode
--help Show this message and exit.
答案 1 :(得分:-1)
使用点击实现此功能是不可能的,因为选项属于它的命令。所有命令都可用的选项应属于包含命令的组。
可以在此处找到实现这一目标的几个实现示例: https://github.com/pallets/click/issues/108