Общие параметры и флаги между командами

Скажем, моя утилита CLI имеет три команды: cmd1, cmd2, cmd3

И я хочу, чтобы cmd3 имел те же параметры и флаги, что и cmd1 и cmd2. Как какое-то наследство.

@click.command()
@click.options("--verbose")
def cmd1():
    pass

@click.command()
@click.options("--directory")
def cmd2():
    pass

@click.command()
@click.inherit(cmd1, cmd2) # HYPOTHETICAL
def cmd3():
    pass

Таким образом, cmd3 будет иметь флаг --verbose и опцию --directory. Возможно ли это сделать с помощью Click? Может быть, я просто что-то упустил в документации...

EDIT: я знаю, что могу сделать это с помощью click.group(). Но тогда все параметры группы должны быть указаны перед командой группы. Я хочу, чтобы все параметры были обычными после команды.

cli.py --verbose --directory /tmp cmd3 -> cli.py cmd3 --verbose --directory /tmp


person jirinovo    schedule 21.10.2016    source источник


Ответы (3)



Определить класс с общими параметрами

class StdCommand(click.core.Command):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.params.insert(0, click.core.Option(('--default-option',), help='Every command should have one'))

Затем передайте класс декоратору при определении функции команды

@click.command(cls=StdCommand)
@click.option('--other')
def main(default_option, other):
  ...
person user10817547    schedule 20.12.2018
comment
Это самое чистое и элегантное решение. Работает без сбоев. Я предлагаю заменить click.core.Command на click.Command. Нет необходимости переходить к нижнему модулю. Кроме того, лучше сказать self.params = [...] вместо вставки в пустой список. - person d0m1n0; 14.08.2020
comment
@ d0m1n0 Первый комментарий абсолютно правильный, а второй - нет. Список не обязательно пустой, вы перезаписываете то, что в нем предложено. Когда вы добавляете дополнительные параметры (--other), они исчезают. - person Lukasz Tracewski; 17.10.2020

Этот код извлекает все параметры из своих аргументов.

def extract_params(*args):
    from click import Command
    if len(args) == 0:
        return ['']
    if any([ not isinstance(a, Command) for a in args ]):
        raise TypeError('Handles only Command instances')

    params = [ p.opts() for cmd_inst in args for p in cmd_inst.params ]
    return list(set(params))

теперь вы можете использовать его:

@click.command()
@click.option(extract_params(cmd1, cmd2))
def cmd3():
    pass

Этот код извлекает только параметры и не извлекает их значения по умолчанию, при необходимости вы можете улучшить его.

person galra    schedule 21.10.2016