I have two Python CLI tools which share a set of common click.options. At the moment, the common options are duplicated:
@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
Is it possible to extract the common options in to a single decorator that can be applied to each function?
You can build your own decorator that encapsulates the common options:
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
Here is a decorator that uses the same principle from the previous answer:
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
And if you want to preserve click's option decorator syntax, you can implement your decorator in this way:
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
If you want to add parameters to such a function, you need to wrap it once more:
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With