Skip to content Skip to sidebar Skip to footer

Require And Option Only If A Choice Is Made When Using Click

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

Solution 1:

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:

Custom Class:

classOptionRequiredIf(click.Option):

    deffull_process_value(self, ctx, value):
        value = super(OptionRequiredIf, self).full_process_value(ctx, value)

        if value isNoneand ctx.params['output'] == 'file':
            msg = 'Required if --output=file'raise click.MissingParameter(ctx=ctx, param=self, message=msg)
        return value

Using Custom Class:

To use the custom class, pass it as the cls argument to the option decorator like:

@click.option('--filename', type=click.STRING, cls=OptionRequiredIf)

Test Code:

import click

@click.command()@click.option('--output',
              type=click.Choice(['stdout', 'file']), default='stdout')@click.option('--filename', type=click.STRING, cls=OptionRequiredIf)defmain(output, filename):
    print("output: " + output)
    if output == 'file':
        if filename isNone:
            print("filename must be provided!")
        else:
            print("filename: " + str(filename))


main('--output=file'.split())

Results:

Usage: test.py [OPTIONS]

Error: Missing option"--filename".  Required if --output=file

Solution 2:

I extended the answer by Stephen, and made it more generic:

classOptionRequiredIf(click.Option):
    """
    Option is required if the context has `option` set to `value`
    """def__init__(self, *a, **k):
        try:
            option = k.pop('option')
            value  = k.pop('value')
        except KeyError:
            raise(KeyError("OptionRequiredIf needs the option and value ""keywords arguments"))

        click.Option.__init__(self, *a, **k)
        self._option = option
        self._value = value

    deffull_process_value(self, ctx, value):
        value = super(OptionRequiredIf, self).full_process_value(ctx, value)
        if value isNoneand ctx.params[self._option] == self._value:
            msg = 'Required if --{}={}'.format(self._option, self._value)
            raise click.MissingParameter(ctx=ctx, param=self, message=msg)
        return value

Usage example:

@click.option('--email', type=click.STRING,
              help='Settings for sending emails.',
              option='output', value='email', cls=OptionRequiredIf)

I was inspired by this answer

Post a Comment for "Require And Option Only If A Choice Is Made When Using Click"