ora*_*nge 5 python python-click
我正在尝试使用Python库Click,但是很难使示例工作。我定义了两组,其中一组(group2)用于处理该组命令的通用参数。我想要实现的是那些通用参数由组函数(group2)处理并分配给上下文变量,因此它们可以由实际命令使用。
一个用例是许多需要用户名和密码的命令,而有些则不需要(甚至不是可选的)。
这是代码
import click
@click.group()
@click.pass_context
def group1(ctx):
pass
@click.group()
@click.option('--optparam', default=None, type=str)
@click.option('--optparam2', default=None, type=str)
@click.pass_context
def group2(ctx, optparam):
print 'in group2', optparam
ctx['foo'] = create_foo_by_processing_params(optparam, optparam2)
@group2.command()
@click.pass_context
def command2a(ctx):
print 'command2a', ctx['foo']
@group2.command()
@click.option('--another-param', default=None, type=str)
@click.pass_context
def command2b(ctx, another_param):
print 'command2b', ctx['foo'], another_param
# many more more commands here...
# @group2.command()
# def command2x():
# ...
@group1.command()
@click.argument('argument1')
@click.option('--option1')
def command1(argument1, option1):
print 'In command2', argument1, option1
cli = click.CommandCollection(sources=[group1, group2])
if __name__ == '__main__':
cli(obj={})
Run Code Online (Sandbox Code Playgroud)
这是使用command2时的结果:
$ python cli-test.py command2 --optparam=123
> Error: no such option: --optparam`
Run Code Online (Sandbox Code Playgroud)
这个例子有什么问题。我试图密切关注文档,但opt-param似乎没有得到认可。
所需方案的基本问题是click.CommandCollection不调用组函数。它直接跳到命令。另外,希望通过装饰器将选项应用到组,但需要通过命令来解析选项。那是:
> my_prog my_command --group-option
Run Code Online (Sandbox Code Playgroud)
代替:
> my_prog --group-option my_command
Run Code Online (Sandbox Code Playgroud)
此click.Group派生类将命令调用挂接到命令,以拦截组参数,并将其传递给group命令。
Group.add_command,将params添加到命令Group.add_command,覆盖command.invokecommand.invoke,将从组中插入的特殊参数放入并将ctx.obj其从中删除paramscommand.invoke,先调用group命令,然后再调用命令本身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
Run Code Online (Sandbox Code Playgroud)
@click.group()
@click.pass_context
def group1(ctx):
pass
@group1.command()
@click.argument('argument1')
@click.option('--option1')
def command1(argument1, option1):
click.echo('In command2 %s %s' % (argument1, option1))
@click.group(cls=GroupWithCommandOptions)
@click.option('--optparam', default=None, type=str)
@click.option('--optparam2', default=None, type=str)
@click.pass_context
def group2(ctx, optparam, optparam2):
# create_foo_by_processing_params(optparam, optparam2)
ctx.obj['foo'] = 'from group2 %s %s' % (optparam, optparam2)
@group2.command()
@click.pass_context
def command2a(ctx):
click.echo('command2a foo:%s' % ctx.obj['foo'])
@group2.command()
@click.option('--another-param', default=None, type=str)
@click.pass_context
def command2b(ctx, another_param):
click.echo('command2b %s %s' % (ctx['foo'], another_param))
cli = click.CommandCollection(sources=[group1, group2])
if __name__ == '__main__':
cli('command2a --optparam OP'.split())
Run Code Online (Sandbox Code Playgroud)
command2a foo:from group2 OP None
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1943 次 |
| 最近记录: |