I am trying to create application with following behaviour:
myapp
- would launch application and do thing A
myapp "some argument"
- would do thing B. Thing B is influenced by argument "some argument".
myapp command
- would launch "command" (denoted by decorator @cli.command
) with feature C. This would be influenced by all the things that click has to offer like @click.option
.
Note, that in my application there would me more commands like C.
I've tried to implement this using this code:
import click
class GroupWithOption(click.Group):
def list_commands(self, ctx):
return ['command']
def get_command(self, ctx, cmd_name):
if cmd_name == 'command':
return command
else:
return do_b
@click.group(cls=GroupWithOption, invoke_without_command=True)
def main():
print("Does A")
@main.command()
def command():
print("Does C")
@main.command()
def do_b():
print("Does B")
if __name__ == '__main__':
main()
This had mixed results. For one, I can invoke 3 different behaviours (or more) very easily, but I wasn't able to figure out, how to pass argument to the B command. I don't like this solution. It doesn't seem to be a clean one. And to function properly, it would require usage of global variables and some nasty hacks.
Does any of you know about a better way, how to accomplish this?
One way to do that is combine the two answers given here:
@click.group(cls=DefaultCommandGroup, invoke_without_command=True)
@click.pass_context
def main(ctx):
if not ctx.invoked_subcommand:
click.echo("Does A")
@main.command(default_command=True)
@click.argument('args', nargs=-1)
def default_cmd_with_args(args):
click.echo("Does B: {}".format(args))
if not ctx.invoked_subcommand:
Allows the group command to be invoked only in the "no command" case, and the
@click.group(cls=DefaultCommandGroup, invoke_without_command=True)
combined with:
@main.command(default_command=True)
allows a command to be run if no other command is found.
import click
@click.group(cls=DefaultCommandGroup, invoke_without_command=True)
@click.pass_context
def main(ctx):
"""My Great CLI"""
if not ctx.invoked_subcommand:
click.echo("Does A")
@main.command(default_command=True)
@click.argument('args', nargs=-1)
def default_cmd_with_args(args):
"""Command run without a command"""
click.echo("Does B: {}".format(args))
@main.command()
def cmd_c1():
"""A c1 command"""
click.echo("Does C1")
@main.command()
def cmd_c2():
"""A c2 command"""
click.echo("Does C2")
if __name__ == "__main__":
commands = (
'',
'random args',
'cmd_c1',
'cmd_c2',
'--help',
)
import sys, time
time.sleep(1)
print('Click Version: {}'.format(click.__version__))
print('Python Version: {}'.format(sys.version))
for command in commands:
try:
time.sleep(0.1)
print('-----------')
print('> ' + command)
time.sleep(0.1)
main(command.split())
except BaseException as exc:
if str(exc) != '0' and \
not isinstance(exc, (click.ClickException, SystemExit)):
raise
Click Version: 6.7
Python Version: 3.6.3 (v3.6.3:2c5fed8, Oct 3 2017, 18:11:49) [MSC v.1900 64 bit (AMD64)]
-----------
>
Does A
-----------
> random args
Does B: ('random', 'args')
-----------
> cmd_c1
Does C1
-----------
> cmd_c2
Does C2
-----------
> --help
Usage: test.py [OPTIONS] COMMAND [ARGS]...
My Great CLI
Options:
--help Show this message and exit.
Commands:
<> Command run without a command
cmd_c1 A c1 command
cmd_c2 A c2 command