1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
|
"""
click_default_group
~~~~~~~~~~~~~~~~~~~
Define a default subcommand by `default=True`:
.. sourcecode:: python
import click
from click_default_group import DefaultGroup
@click.group(cls=DefaultGroup, default_if_no_args=True)
def cli():
pass
@cli.command(default=True)
def foo():
click.echo('foo')
@cli.command()
def bar():
click.echo('bar')
Then you can invoke that without explicit subcommand name:
.. sourcecode:: console
$ cli.py --help
Usage: cli.py [OPTIONS] COMMAND [ARGS]...
Options:
--help Show this message and exit.
Command:
foo*
bar
$ cli.py
foo
$ cli.py foo
foo
$ cli.py bar
bar
"""
import warnings
import click
__all__ = ['DefaultGroup']
__version__ = '1.2.4'
class DefaultGroup(click.Group):
"""Invokes a subcommand marked with `default=True` if any subcommand not
chosen.
:param default_if_no_args: resolves to the default command if no arguments
passed.
"""
def __init__(self, *args, **kwargs):
# To resolve as the default command.
if not kwargs.get('ignore_unknown_options', True):
raise ValueError('Default group accepts unknown options')
self.ignore_unknown_options = True
self.default_cmd_name = kwargs.pop('default', None)
self.default_if_no_args = kwargs.pop('default_if_no_args', False)
super(DefaultGroup, self).__init__(*args, **kwargs)
def set_default_command(self, command):
"""Sets a command function as the default command."""
cmd_name = command.name
self.add_command(command)
self.default_cmd_name = cmd_name
def parse_args(self, ctx, args):
if not args and self.default_if_no_args:
args.insert(0, self.default_cmd_name)
return super(DefaultGroup, self).parse_args(ctx, args)
def get_command(self, ctx, cmd_name):
if cmd_name not in self.commands:
# No command name matched.
ctx.arg0 = cmd_name
cmd_name = self.default_cmd_name
return super(DefaultGroup, self).get_command(ctx, cmd_name)
def resolve_command(self, ctx, args):
base = super(DefaultGroup, self)
cmd_name, cmd, args = base.resolve_command(ctx, args)
if hasattr(ctx, 'arg0'):
args.insert(0, ctx.arg0)
cmd_name = cmd.name
return cmd_name, cmd, args
def format_commands(self, ctx, formatter):
formatter = DefaultCommandFormatter(self, formatter, mark='*')
return super(DefaultGroup, self).format_commands(ctx, formatter)
def command(self, *args, **kwargs):
default = kwargs.pop('default', False)
decorator = super(DefaultGroup, self).command(*args, **kwargs)
if not default:
return decorator
warnings.warn('Use default param of DefaultGroup or '
'set_default_command() instead', DeprecationWarning)
def _decorator(f):
cmd = decorator(f)
self.set_default_command(cmd)
return cmd
return _decorator
class DefaultCommandFormatter(object):
"""Wraps a formatter to mark a default command."""
def __init__(self, group, formatter, mark='*'):
self.group = group
self.formatter = formatter
self.mark = mark
def __getattr__(self, attr):
return getattr(self.formatter, attr)
def write_dl(self, rows, *args, **kwargs):
rows_ = []
for cmd_name, help in rows:
if cmd_name == self.group.default_cmd_name:
rows_.insert(0, (cmd_name + self.mark, help))
else:
rows_.append((cmd_name, help))
return self.formatter.write_dl(rows_, *args, **kwargs)
|