I'm having a conundrum with the Python Click library when parsing some CLI options.
I would like an option to act as a flag by itself, but optionally accept string values. E.g.:
$ myscript
⇒ option = False
$ myscript -o
⇒ option = True
$ myscript -o foobar
⇒ option = Foobar
Additionally, I would like the option to be "eager" (e.g. in "Click" terms abort execution after a callback), but this can be ignored for now.
When I define my arguments like this:
@click.command()
@click...
@click.option("-o", "option", is_flag=True, default=False)
def myscript(..., option):
I achieve example 1 and 2, but 3 is naturally impossible because the flag detects present/not present only.
When I define my arguments like this:
@click.command()
@click...
@click.option("-o", "--option", default="") # Let's assume I will cast empty string to False
def myscript(..., option):
I achieve 1 and 3, but 2 will fail with an Error: -c option requires an argument
.
This does not seems like an out-of-this world scenario, but I can't seem to be able to achieve this or find examples that behave like this.
How can I define an @click.option
that gets parsed like:
False
when not setTrue
when set but without valuestr
when set with valueOne way that I have managed to achieve this behaviour was by actually using arguments as below. I'll post this as a workaround, while I try to see if it could be done with an option, and I'll update my post accordingly
@click.command(context_settings={"ignore_unknown_options": True})
@click.argument("options", nargs=-1)
def myscript(options):
option = False
if options is ():
option = False
if '-o' in options or '--option' in options:
option = True
if len(options) > 1:
option = options[1]
print(option)
Later Edit Using an option, I have managed to achieve this by adding an argument to the command definition.
@click.command()
@click.option('-o', '--option', is_flag=True, default=False, is_eager=True)
@click.argument('value', nargs=-1)
def myscript(option, value):
if option and value != ():
option = value[0]
print(option)
The nargs
can be removed if you only expect at most one argument to follow, and can be treated as not required.
@click.command()
@click.option('-o', '--option', is_flag=True, default=False, is_eager=True)
@click.argument('value', required=False)
def myscript(option, value=None):
if option and value is not None:
option = value
print(option)
It might also be possible by putting together a context generator and storing some state, but that seems the least desirable solution, since you would be relying on the context storing your state.
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