Click Group Chained Subcommands

Build chained Click subcommands where multiple steps run in sequence, sharing a result context and enforcing invocation order.

PythonCli Tooling

Code

snippet
import click


@click.group(chain=True)
@click.option('--verbose', is_flag=True, help='enable verbose output')
@click.pass_context
def cli(ctx, verbose):
    ctx.ensure_object(dict)
    ctx.obj['verbose'] = verbose
    ctx.obj['results'] = []


@cli.command('extract')
@click.argument('source', type=click.Path(exists=True))
@click.pass_obj
def extract(state, source):
    click.echo(f'extracting {source}')
    state['results'].append(('extract', source))


@cli.command('transform')
@click.option('--uppercase', is_flag=True)
@click.pass_obj
def transform(state, uppercase):
    if not any(step == 'extract' for step, _ in state['results']):
        raise click.UsageError('transform must run after extract')
    value = 'transformed-data'
    if uppercase:
        value = value.upper()
    state['results'].append(('transform', value))
    click.echo(f'transform ok: {value}')


@cli.result_callback()
def process_pipeline(pipeline, state, **kwargs):
    click.echo('pipeline finished:')
    for step, value in state['results']:
        click.echo(f'  {step} -> {value}')


if __name__ == '__main__':
    cli()