Search code examples
pythoncommand-line-interfacepython-click

Shared options and flags between commands


Say my CLI utility has three commands: cmd1, cmd2, cmd3

And I want cmd3 to have same options and flags as cmd1 and cmd2. Like some sort of inheritance.

@click.command()
@click.options("--verbose")
def cmd1():
    pass

@click.command()
@click.options("--directory")
def cmd2():
    pass

@click.command()
@click.inherit(cmd1, cmd2) # HYPOTHETICAL
def cmd3():
    pass

So cmd3 will have flag --verbose and option --directory. Is it possible to make this with Click? Maybe I just have overlooked something in the documentation...

EDIT: I know that I can do this with click.group(). But then all the group's options must be specified before group's command. I want to have all the options normally after command.

cli.py --verbose --directory /tmp cmd3 -> cli.py cmd3 --verbose --directory /tmp


Solution

  • I have found a simple solution! I slightly edited the snippet from https://github.com/pallets/click/issues/108 :

    import click
    
    
    _cmd1_options = [
        click.option('--cmd1-opt')
    ]
    
    _cmd2_options = [
        click.option('--cmd2-opt')
    ]
    
    
    def add_options(options):
        def _add_options(func):
            for option in reversed(options):
                func = option(func)
            return func
        return _add_options
    
    
    @click.group()
    def group(**kwargs):
        pass
    
    
    @group.command()
    @add_options(_cmd1_options)
    def cmd1(**kwargs):
        print(kwargs)
    
    
    @group.command()
    @add_options(_cmd2_options)
    def cmd2(**kwargs):
        print(kwargs)
    
    
    @group.command()
    @add_options(_cmd1_options)
    @add_options(_cmd2_options)
    @click.option("--cmd3-opt")
    def cmd3(**kwargs):
        print(kwargs)
    
    
    if __name__ == '__main__':
        group()