我有两个Python CLI工具,它们共享一组常见的click.options。目前,共同的选项是重复的:
@click.command()
@click.option('--foo', is_flag=True)
@click.option('--bar', is_flag=True)
@click.option('--unique-flag-1', is_flag=True)
def command_one():
pass
@click.command()
@click.option('--foo', is_flag=True)
@click.option('--bar', is_flag=True)
@click.option('--unique-flag-2', is_flag=True)
def command_two():
pass
是否可以将共同选项提取到可以应用于每个功能的单个装饰器中?
您可以构建自己的装饰器,该装饰符封装共同选项:
def common_options(function):
function = click.option('--unique-flag-1', is_flag=True)(function)
function = click.option('--bar', is_flag=True)(function)
function = click.option('--foo', is_flag=True)(function)
return function
@click.command()
@common_options
def command():
pass
,如果要保留点击的选项deconator语法,则可以以这种方式实现装饰器:
import functools
def common_options(f):
@click.option('--foo', is_flag=True)
@click.option('--bar', is_flag=True)
@functools.wraps(f)
def wrapper_common_options(*args, **kwargs):
return f(*args, **kwargs)
return wrapper_common_options
@click.command()
@common_options
@click.option('--unique-flag-1', is_flag=True)
def command_one():
pass
这是一个装饰器,使用了以前的答案中相同的原理:
def group_options(*options):
def wrapper(function):
for option in reversed(options):
function = option(function)
return function
return wrapper
opt_1 = click.option("--example1")
opt_2 = click.option("--example2")
opt_3 = click.option("--example3")
@cli.command()
@click.option("--example0")
@group_options(opt_1, opt_2, opt_3)
def command(example0, example1, example2, example3):
pass
如果要在此功能中添加参数,则需要再次包装它:
def common_options(mydefault=True):
def inner_func(function):
function = click.option('--unique-flag-1', is_flag=True)(function)
function = click.option('--bar', is_flag=True)(function)
function = click.option('--foo', is_flag=True, default=mydefault)(function)
return function
return inner_func
@click.command()
@common_options(mydefault=False)
def command():
pass
对于单个可重复使用的选项,我只是将click.option
返回的装饰器存储在变量中。对于多种常用选择,我喜欢使用简单的构图作为助手。
import functools
compose = lambda *funcs: functools.reduce(lambda f, g: lambda x: f(g(x)), funcs)
# reusable single option or argument
spam = click.option("--spam")
# reusable group
foo_bar_baz = compose(
click.option("--foo", is_flag=True),
click.option("--bar", is_flag=True),
click.option("--baz", is_flag=True),
)
@click.command()
@foo_bar_baz
@spam
def command1(foo, bar, baz, spam):
pass
@click.command()
@foo_bar_baz
@spam
@click.option('--unique-flag', is_flag=True)
def command2(foo, bar, baz, spam, unique_flag):
pass