When using click
I know how to define a multiple choice option. I also know how to set an option as a required one. But, how can I indicate that an option B
is required only if the value of option A
is foo
?
Here's an example:
import click
@click.command()
@click.option('--output',
type=click.Choice(['stdout', 'file']), default='stdout')
@click.option('--filename', type=click.STRING)
def main(output, filename):
print("output: " + output)
if output == 'file':
if filename is None:
print("filename must be provided!")
else:
print("filename: " + str(filename))
if __name__ == "__main__":
main()
If the output
option is stdout
, then filename
is not needed. However, if the user chooses output
to be file
, then the other option filename
must be provided. Is this pattern supported by click?
At the beginning of the function I can add something like:
if output == 'file' and filename is None:
raise ValueError('When output is "file", a filename must be provided')
But I am interested whether there's a nicer/cleaner solution.
A user interface technique for Mac computers, where the Option key is depressed and held down while the mouse is clicked on an item onscreen. Depending on the context — what is clicked, which app is active, etc., — a variety of functions may be initiated.
Python click simple example The example creates a command that outputs a message. Click uses the echo instead of the print . It increases compatibility and adds colouring support. $ ./simple.py Hello there $ ./simple.py --help Usage: simple.py [OPTIONS] Options: --help Show this message and exit.
This is a special attribute where commands are supposed to remember what they need to pass on to their children. In order for this to work, we need to mark our function with pass_context() , because otherwise, the context object would be entirely hidden from us.
Click, or “Command Line Interface Creation Kit” is a Python library for building command line interfaces. The three main points of Python Click are arbitrary nesting of commands, automatic help page generation, and supporting lazy loading of subcommands at runtime.
In the particular case of this example, I think an easier method would be to get rid of --output
, and simply assume stdout
if --filename
is not specified and if --filename
is specified, then use it instead of stdout
.
But assuming this is a contrived example, you can inherit from click.Option
to allow hooking into the click processing:
class OptionRequiredIf(click.Option):
def full_process_value(self, ctx, value):
value = super(OptionRequiredIf, self).full_process_value(ctx, value)
if value is None and ctx.params['output'] == 'file':
msg = 'Required if --output=file'
raise click.MissingParameter(ctx=ctx, param=self, message=msg)
return value
To use the custom class, pass it as the cls argument to the option decorator like:
@click.option('--filename', type=click.STRING, cls=OptionRequiredIf)
import click
@click.command()
@click.option('--output',
type=click.Choice(['stdout', 'file']), default='stdout')
@click.option('--filename', type=click.STRING, cls=OptionRequiredIf)
def main(output, filename):
print("output: " + output)
if output == 'file':
if filename is None:
print("filename must be provided!")
else:
print("filename: " + str(filename))
main('--output=file'.split())
Usage: test.py [OPTIONS]
Error: Missing option "--filename". Required if --output=file
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