Refactor @click.option() arguments

42 views Asked by At

Say I have this (minimal example from a larger script):

import click

@click.command()
@click.option('--foo', required=True)
def bar1(foo: str) -> None:
    print(f"bar1: {foo}")

@click.command()
@click.option('--foo', required=True)
def bar2(foo: str) -> None:
    print(f"bar2: {foo}")

if __name__ == '__main__':
    bar1() # these are actually called from a poetry scripts section in pyproject.toml
    # bar2()

I would like to avoid repeating the same option --foo with the same arguments for both bar1 and bar2. Maybe something like

@click.option(*ClickOptions.foo)

but this does not work since option foo also takes keyword argument required=True. I would like to avoid splitting it up like this:

@click.option(*ClickOptions.foo.args, **ClickOptions.foo.kwargs)

Is there an elegant way to do this?

1

There are 1 answers

0
afterburner On

To expand on @Louis Lac's response, I defined my own decorator like this, which you can use like any other decorator on the group/command


_global_options = [
    click.option('-v', '--verbose', count=True, default=0, help='Verbose output.'),
    click.option('-n', '--dry-run', is_flag=True, default=False, help='Dry-run mode.')
]


def common_options(func):
    for option in reversed(_global_options):
        func = option(func)
    return func

@click.group()
@common_options
def cli(**kwargs):
    pass