Вы можете использовать пользовательский класс click.Command
для автоматической вставки --
, где это необходимо, например:
Пользовательский класс:
class RealNargsMinusOne(click.Command):
def parse_args(self, ctx, args):
orig_args = list(args)
try:
return super(RealNargsMinusOne, self).parse_args(ctx, args)
except click.NoSuchOption as exc:
first_unknown = str(exc).split()[-1]
position_unknown = orig_args.index(first_unknown)
orig_args.insert(position_unknown, '--')
return super(RealNargsMinusOne, self).parse_args(ctx, orig_args)
Использование пользовательского класса:
Чтобы использовать пользовательский класс, передайте его в качестве аргумента cls
декоратору команды, например:
@click.command(cls=RealNargsMinusOne)
....
def my_command():
....
Как это работает?
Это работает, потому что click - это хорошо спроектированная OO-инфраструктура. Декоратор @click.command()
обычно создает экземпляр объекта click.Command
, но позволяет переопределить это поведение параметром cls
. Так что сравнительно легко унаследовать от click.Command
в нашем собственном классе и переопределить нужные методы.
В этом случае мы переходим click.Command.parse_args()
и ловим исключение click.NoSuchOption
. Затем мы изменяем список аргументов с --
перед опцией-нарушителем и повторяем синтаксический анализ.
Тестовый код:
import click
@click.command(cls=RealNargsMinusOne)
@click.option('-v', '--verbose', is_flag=True)
@click.argument('target')
@click.argument('command', nargs=-1)
def my_command(verbose, target, command):
print('verbose:', verbose)
print('target:', target)
print('command:', command)
if __name__ == "__main__":
commands = (
'-v hostname echo -e foo',
'-v hostname -x echo -e foo',
'-x hostname -x echo -e foo',
'--help',
'',
)
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)
my_command(cmd.split(), allow_extra_args=True)
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)]
-----------
> -v hostname echo -e foo
verbose: True
target: hostname
command: ('echo', '-e', 'foo')
-----------
> -v hostname -x echo -e foo
verbose: True
target: hostname
command: ('-x', 'echo', '-e', 'foo')
-----------
> -x hostname -x echo -e foo
verbose: False
target: -x
command: ('hostname', '-x', 'echo', '-e', 'foo')
-----------
> --help
Usage: test.py [OPTIONS] TARGET [COMMAND]...
Options:
-v, --verbose
--help Show this message and exit.
-----------
>
Usage: test.py [OPTIONS] TARGET [COMMAND]...
Error: Missing argument "target".