Search code examples
pythonpython-click

Creating commands with multiple arguments pick one


I'm trying to create a Click based command line interface, and I've found CLI to be sufficient, however I can't seem to figure out how I should design it. So far I have the below code which creates 4 commands. However what I ideally want is something like this:

commands:
cli.py env delete NAME
cli.py env list
cli.py source delete NAME
cli.py source list

my current code:

@click.group()
@click.version_option()
def cli():
    """First paragraph.
    """

@cli.command()
def list_env():
    "list env"

@cli.command()
def delete_env(name):
    "Delete enviroment"

@cli.command()
def list_source():
    "list source"

def delete_source(name):
    "Delete source"

if __name__ == '__main__':
    cli()

Solution

  • What you are trying to do can be done with sub-groups. The key is to declare two more groups (ie: env and source) that are sub-groups of cli, and then the commands (ie: list and delete) will be associated with the sub-groups like:

    Code:

    import click
    
    @click.group()
    @click.version_option()
    def cli():
        """First paragraph.
        """
    
    @cli.group()
    def env():
        """env sub-command"""
    
    @env.command('list')
    def list_():
        click.echo("env list")
    
    @env.command()
    @click.argument('name')
    def delete(name):
        click.echo("env delete %s" % name)
    
    @cli.group()
    def source():
        """source sub-command"""
    
    @source.command('list')
    def list_():
        click.echo("source list")
    
    @source.command()
    @click.argument('name')
    def delete(name):
        click.echo("source delete %s" % name)
    

    Test Code:

    if __name__ == '__main__':
        #cli('env list'.split())
        cli('env delete a_name'.split())
        #cli('source list'.split())
        #cli('source delete a_name'.split())
    

    Results:

    env delete a_name