I am trying to accomplish something not very standard for CLI parsing with Click and it only works partially:
Sample:
import click
@click.group()
@click.argument('hostname', required=False)
@click.pass_context
def cli(ctx, hostname=None):
""""""
ctx.obj = hostname
click.echo("cli: hostname={}".format(hostname))
@cli.command()
@click.pass_obj
def check(hostname):
click.echo("check: hostname={}".format(hostname))
@cli.command()
@click.pass_obj
def show(hostname):
click.echo("check: hostname={}".format(hostname))
if __name__ == '__main__':
cli()
The part WITH the hostname works:
> pipenv run python cli.py localhost check
cli: hostname=localhost
check: hostname=localhost
> pipenv run python cli.py localhost show
cli: hostname=localhost
check: hostname=localhost
But the part WITHOUT the hostname DOES NOT:
> pipenv run python cli.py show
Usage: cli.py [OPTIONS] [HOSTNAME] COMMAND [ARGS]...
Error: Missing command.
Anybody has an idea about the direction I should start looking into?
This can be done by over riding the click.Group
argument parser like:
Custom Class:
class MyGroup(click.Group):
def parse_args(self, ctx, args):
if args[0] in self.commands:
if len(args) == 1 or args[1] not in self.commands:
args.insert(0, '')
super(MyGroup, self).parse_args(ctx, args)
Using Custom Class:
Then to use the custom group, pass it as the cls
argument to the group
decorator like:
@click.group(cls=MyGroup)
@click.argument('hostname', required=False)
@click.pass_context
def cli(ctx, hostname=None):
....
How?
This works because click
is a well designed OO framework. The @click.group()
decorator usually instantiates a click.Group
object but allows this behavior to be over ridden with the cls
parameter. So it is a relatively easy matter to inherit from click.Group
in our own class and over ride desired methods.
In this case we over ride click.Group.parse_args()
and if the first parameter matches a command and the second parameter does not, then we insert an empty string as the first parameter. This puts everything back where the parser expects it to be.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With