Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Creating a wrapper decorator for click.options()

I am trying to create a wrapper decorator for the click decorator @click.options('--foo', required=True):

import click

def foo_option(func):
    orig_decorator = click.option('--foo', required=True)(func)
    def decorator(*args, **kwargs):
        orig_decorator(*args, **kwargs)
    return decorator

@click.command()
@foo_option
def bar1(foo: str) -> None:
    print(f"bar1: {foo}")

if __name__ == '__main__':
    bar1()

This does not work. When I run it like script.py --foo=1 I get error:

Usage: script.py [OPTIONS]
Try 'script.py --help' for help.

Error: No such option: --foo

Expected output should be:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

bar1: 1

What am I missing?
See Refactor @click.option() arguments for background information.

>Solution :

The issue is with how you have structured the decorator. In this case, you are wrapping around the click.option which is unnecessary. When you create a decorator to wrap around another decorator (like click.option), you should consider that decorators work from bottom to top. here is the updated code:

import click


def foo_option(func):
    return click.option('--foo', required=True)(func)


@click.command()
@foo_option
def bar1(foo: str) -> None:
    print(f"bar1: {foo}")


if __name__ == '__main__':
    bar1()

When you run the script, you will get the expected output.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading