Нажмите группу с параметрами и командами одновременно - PullRequest
0 голосов
/ 27 февраля 2019

Я пытаюсь создать приложение со следующим поведением:

myapp - будет запускать приложение и делать что-то A

myapp "some argument" - будет делать то, что B. На B влияет под влияниемАргумент "некоторый аргумент".

myapp command - запустит "команду" (обозначаемую декоратором @cli.command) с функцией C. На это будут влиять все вещи, которые должен предлагать клик, например @click.option,

Обратите внимание , что в моем приложении я бы больше команд , как C.


Я пытался реализовать это с помощью этогокод:

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()

Это привело к смешанным результатам.С одной стороны, я могу очень легко вызвать 3 различных поведения (или более), но я не смог понять, как передать аргумент команде B. Мне не нравится это решение. Оно не кажется чистым.И для правильной работы это потребует использования глобальных переменных и некоторых неприятных хаков.

Кто-нибудь из вас знает о лучшем способе, как этого добиться?

1 Ответ

0 голосов
/ 28 февраля 2019

Один из способов сделать это - объединить два ответа, данные здесь :

Ключевые элементы:

@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:

Позволяет групповой команде вызываться только в случае "без команды", а

@click.group(cls=DefaultCommandGroup, invoke_without_command=True)

в сочетании с:

@main.command(default_command=True)

позволяет запускать команду, еслидругие команды не найдены.

Код теста:

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
...