Я хочу передать неограниченное количество параметров клику CLI. Я также не знаю имена опций. Я обойду эту проблему, используя опцию conf
. Он принимает строку, которая предполагается представлять собой объект JSON.
Что я сделал:
@click.command()
@click.option('--conf', type=str)
def dummy(conf):
click.echo('dummy param {}'.format(conf))
Как я его использую:
>python main.py dummy --conf='{"foo": "bar", "fizz": "buzz"}'
Что я хочу сделать:
@click.command()
#some magic stuff
def dummy(**kwargs):
click.echo('dummy param {}'.format(**kwargs))
Как я хочу его использовать:
>python main.py dummy --foo=bar --fizz=buzz
Вы можете подключить синтаксический анализатор и сообщить ему о каждом параметре, указанном в командной строке, например:
import click
class AcceptAllCommand(click.Command):
def make_parser(self, ctx):
"""Hook 'make_parser' and allow the opt dict to find any option"""
parser = super(AcceptAllCommand, self).make_parser(ctx)
command = self
class AcceptAllDict(dict):
def __contains__(self, item):
"""If the parser does no know this option, add it"""
if not super(AcceptAllDict, self).__contains__(item):
# create an option name
name = item.lstrip('-')
# add the option to our command
click.option(item)(command)
# get the option instance from the command
option = command.params[-1]
# add the option instance to the parser
parser.add_option([item], name, obj=option)
return True
# set the parser options to our dict
parser._short_opt = AcceptAllDict(parser._short_opt)
parser._long_opt = AcceptAllDict(parser._long_opt)
return parser
Чтобы использовать пользовательский класс, просто передайте класс click.command()
например:
@click.command(cls=AcceptAllCommand)
def my_command(**kwargs):
...
Это работает, потому что клик - это хорошо разработанная OO-структура. @click.command()
обычно создает экземпляр объекта click.Command
но позволяет этому поведению click.Command
параметр cls
. Так что относительно легко наследовать от click.Command
в нашем собственном классе и над click.Command
желаемые методы.
В этом случае мы переопределяем make_parser()
и заменяем опцию dicts собственным классом dict
. В нашем dict
мы переопределяем магический метод __contains__()
, и в нем мы заполняем синтаксический анализатор опцией, соответствующей __contains__()
имени, если это имя еще не существует.
@click.command(cls=AcceptAllCommand)
def dummy(**kwargs):
click.echo('dummy param: {}'.format(kwargs))
if __name__ == "__main__":
import time
cmd = '--foo=bar --fizz=buzz'
print('Click Version: {}'.format(click.__version__))
print('Python Version: {}'.format(sys.version))
print('-----------')
print('> ' + cmd)
time.sleep(0.1)
dummy(cmd.split())
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)]
-----------
> --foo=bar --fizz=buzz
dummy param: {'foo': 'bar', 'fizz': 'buzz'}