Как создать исключение для группового действия в клике - PullRequest
0 голосов
/ 10 мая 2018

У меня есть случай, когда я хотел бы запустить общую функцию (check_upgrade()) для большинства моих команд нажатия, но есть несколько случаев, когда я не хочу ее запускать. Вместо того чтобы полагаться на то, что разработчики не забывают добавить декоратор или вызов функции для явного запуска этой проверки, я бы предпочел вместо этого запустить ее по умолчанию, а затем иметь декоратор, который можно добавить (например, @bypass_upgrade_check) для команд, где check_upgrade() не должен бежать.

Я надеялся на что-то вроде:

class State(object):
    def __init__(self):
        self.bypass_upgrade_check = False

pass_state = click.make_pass_decorator(State, ensure=True)

def bypass_upgrade_check(func):
    @pass_state
    def wrapper(state, *args, **kwargs):
        state.bypass_upgrade_check = True
        func(*args, **kwargs)
    return wrapper 

@click.group()
@pass_state
def common(state):
    if not state.bypass_upgrade_check:
        check_upgrade()

@common.command()
def cmd1():
    # check_upgrade() runs here
    pass

@bypass_upgrade_check
@common.command()
def cmd2():
    # don't run check_upgrade() here
    pass

Но это не работает. На самом деле он никогда не вызывает функцию bypass_upgrade_check().

Есть ли способ украсить команду таким образом, чтобы я мог изменить состояние перед выполнением кода группы? Или вообще другой метод, который выполняет это?

1 Ответ

0 голосов
/ 10 мая 2018

Чтобы отслеживать, какие команды обходят проверку обновления, я предлагаю, чтобы в декораторе маркировки обхода вы сохраняли это состояние на объекте click.Command. Затем, если вы передадите click.Context своей группе, вы можете посмотреть на объект команды, чтобы увидеть, отмечен ли он, чтобы разрешить пропуск обновления, например:

Код:

def bypass_upgrade_check(func):
    setattr(func, 'do_upgrade_check', False)

@click.group()
@click.pass_context
def cli(ctx):
    sub_cmd = ctx.command.commands[ctx.invoked_subcommand]
    if getattr(sub_cmd, 'do_upgrade_check', True):
        check_upgrade()

Тестовый код:

import click

def check_upgrade():
    click.echo('Checking Upgrade!')

def bypass_upgrade_check(func):
    setattr(func, 'do_upgrade_check', False)

@click.group()
@click.pass_context
def cli(ctx):
    sub_cmd = ctx.command.commands[ctx.invoked_subcommand]
    if getattr(sub_cmd, 'do_upgrade_check', True):
        check_upgrade()

@cli.command()
def cmd1():
    # check_upgrade() runs here
    click.echo('cmd1')

@bypass_upgrade_check
@cli.command()
def cmd2():
    # don't run check_upgrade() here
    click.echo('cmd2')


if __name__ == "__main__":
    commands = (
        'cmd1',
        'cmd2',
    )

    import sys, time

    time.sleep(1)
    print('Click Version: {}'.format(click.__version__))
    print('Python Version: {}'.format(sys.version))
    for cmd in commands:
        try:
            time.sleep(0.1)
            print('-----------')
            print('> ' + cmd)
            time.sleep(0.1)
            cli(cmd.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)]
-----------
> cmd1
Checking Upgrade!
cmd1
-----------
> cmd2
cmd2
...