在my initial question的基础上,我希望能够在运行回调之前运行父组的主体。在
I have a case where I'd like to automatically run a common function, check_upgrade(), for most of my click commands and sub-commands, but there are a few cases where I don't want to run it. I was thinking I could have a decorator that one can add (e.g. @bypass_upgrade_check) for commands where check_upgrade() should not run.
例如:
def do_upgrade():
print("Performing upgrade")
bypass_upgrade_check = make_exclude_hook_group(do_upgrade)
@click.group(cls=bypass_upgrade_check())
@click.option('--arg1', default=DFLT_ARG1)
@click.option('--arg2', default=DFLT_ARG2)
@click.pass_context
def cli(ctx, arg1, arg2):
config.call_me_before_upgrade_check(arg1, arg2)
@bypass_upgrade_check
@cli.command()
def top_cmd1():
click.echo('cmd1')
@cli.command()
def top_cmd2():
click.echo('cmd2')
@cli.group()
def sub_cmd_group():
click.echo('sub_cmd_group')
@bypass_upgrade_check
@sub_cmd_group.command()
def sub_cmd1():
click.echo('sub_cmd1')
@sub_cmd_group.command()
def sub_cmd2():
click.echo('sub_cmd2')
我希望事情像the initial question中解释的那样运行,但是在执行cli()
的主体之前执行do_upgrade()
,我希望它调用:
例如。或者对于嵌套命令:
cli() --> sub_cmd_group() --> do_upgrade() --> sub_cmd1()
所以我想用另一种方式来表达这个问题:是否可以从原始问题中获得功能,但是在子命令本身运行之前调用回调,而不是在任何组块运行之前被调用?在
我之所以需要这样做,是因为传入顶级CLI命令的参数指示要检查升级的服务器地址。我需要这些信息来处理do_upgrade()
。我无法将此信息直接传递给do_upgrade()
,因为此服务器信息也在应用程序的其他地方使用。我可以从do_upgrade()
用类似于config.get_server()
的方式查询它。在
与original question类似,解决此问题的一种方法是构建一个与自定义}之后调用:
click.Group
类成对出现的自定义装饰器。增加的复杂性是钩住Command.invoke()
而不是Group.invoke()
,这样回调将在Command.invoke()
之前立即调用,因此将在任何{自定义装饰生成器:
使用装饰生成器:
要使用decorator,我们首先需要构建decorator,如下所示:
^{pr2}$然后我们需要将其用作自定义类
click.group()
,例如:最后,我们可以将不需要使用回调的任何命令或子命令修饰为组:
这是怎么回事?
这是因为click是一个设计良好的OO框架。
@click.group()
修饰符通常实例化一个click.Group
对象,但允许使用cls
参数覆盖此行为。因此,在我们自己的类中从click.Group
继承并超越所需的方法是一件相对容易的事情。在本例中,我们构建了一个decorator,它为任何不需要调用回调的click函数设置属性。然后在我们的自定义组中,我们覆盖了
group()
和command()
修饰符,这样我们就可以在命令上对invoke()
进行猴子补丁,如果要执行的命令还没有被修饰,则调用回调。测试代码:
结果:
相关问题 更多 >
编程相关推荐