Get the parameters passed to the click.group () subcommand
If I have click.group()
with multiple subcommands, is there a way that I can get the command line arguments passed to those subcommands within the group itself?
I know that you can go from group down through context
and I know that I can use a function callback
to be executed before the command, but I didn't know if there is a better way to do this than use callback
.
Example:
@click.group()
def cli():
pass
@cli.command()
@click.argument('task')
@click.argument('task_id')
def sync(task, task_id):
click.echo('Synching: {}'.format(task))
In this example, is there a way to get task
or task_id
in a group method?
source to share
This can be done with a method click.Group.invoke()
like:
Custom class:
class MyGroup(click.Group):
def invoke(self, ctx):
ctx.obj = tuple(ctx.args)
super(MyGroup, self).invoke(ctx)
Using a custom class:
Then, to use a custom group, pass it as an argument cls
to the decorator group
, for example:
@click.group(cls=MyGroup)
@click.pass_context
def cli(ctx):
args = ctx.obj
....
How it works?
It works because it click
is a well-designed OO framework. The decorator @click.group()
usually instantiates the object click.Group
, but allows this behavior to exceed the parameter cls
. So it's relatively easy to inherit from click.Group
in our own class and overcome the desired methods.
In this case, we click.Group.invoke()
'll go through and take the arguments and put them in the box ctx.obj
. They are then available in the function cli()
.
Test code:
import click
class MyGroup(click.Group):
def invoke(self, ctx):
ctx.obj = tuple(ctx.args)
super(MyGroup, self).invoke(ctx)
@click.group(cls=MyGroup)
@click.pass_context
def cli(ctx):
args = ctx.obj
click.echo('cli: {} {}'.format(ctx.invoked_subcommand, ' '.join(args)))
@cli.command()
@click.argument('task')
@click.argument('task_id')
def sync(task, task_id):
click.echo('Synching: {}'.format(task))
cli('sync task taskid'.split())
Results:
cli: sync task taskid
Synching: task
source to share