-1

I am writing a command line interface using python click library and I want to enforce users to pass only one option at a time to the click command and it should return an error if user pass both the options at the same time. Is there a way to do this in click?

@click.command()
@click.option('--tag', required=False)
@click.option('--filename’, required=False, type=click.Path(exists=True, file_okay=True)")
@click.option('--noverbose', is_flag=True, required=False, default=False)
def init(tag=False,configfile=False,noverbose=False):
   if filename and noverbose:
        raise click.ClickException(
            "Invalid choice of options: '--filename' and '--noverbose' cannot be used at the same time.")
nad87563
  • 3,672
  • 7
  • 32
  • 54
  • 1
    I think this question was already discussed here: https://stackoverflow.com/q/37310718/687896 – Brandt Mar 10 '22 at 15:46

1 Answers1

0

Changing this answer desired program will be

import click

class Mutex(click.Option):
    def __init__(self, *args, **kwargs):
        self.not_required_if: list = kwargs.pop("not_required_if")

        assert self.not_required_if, "'not_required_if' parameter required"
        kwargs["help"] = (kwargs.get("help", "") + "Option is mutually exclusive with " +
                          ", ".join(self.not_required_if) + ".").strip()
        super(Mutex, self).__init__(*args, **kwargs)

    def handle_parse_result(self, ctx, opts, args):
        current_opt: bool = self.name in opts
        for mutex_opt in self.not_required_if:
            if mutex_opt in opts:
                if current_opt:
                    raise click.UsageError(
                        "Illegal usage: '" + str(self.name) + "' is mutually exclusive with " + str(mutex_opt) + ".")
                else:
                    self.prompt = None
        return super(Mutex, self).handle_parse_result(ctx, opts, args)


@click.command()
@click.option('--tag', required=False)
@click.option('--filename', required=False, type=click.Path(exists=True, file_okay=True), cls=Mutex, not_required_if=["noverbose"])
@click.option('--noverbose', is_flag=True, required=False, default=False, cls=Mutex, not_required_if=["file_name"],)
def init(tag=False, configfile=False, noverbose=False, filename=None):
    print("funtion init")

if __name__ == '__main__':
    init()

Output

$ python3 cc.py --filename catwalk_2.0.2-6.dsc
funtion init

$ python3 cc.py --filename catwalk_2.0.2-6.dsc --noverbose
Error: Illegal usage: 'filename' is mutually exclusive with noverbose.
EsmaeelE
  • 2,331
  • 6
  • 22
  • 31