gpt4 book ai didi

python - 动态指定选项和参数

转载 作者:行者123 更新时间:2023-12-01 01:53:27 32 4
gpt4 key购买 nike

我想从数据库加载参数和选项。我允许用户定义自己的选项和参数。用户可以通过命令行调用远程api。它们指定端点的 URL 和参数。这是数据库中的数据的样子

[
{
"name": "thename1",
"short": "a",
"long": "ace"
"type": "string",
"required": false
},
{
"name": "thename2",
"short": "b",
"long": "bravo"
"type": "number",
"required": true
},
{
"name": "thename3",
"short": "c",
"long": "candy"
"type": "array",
"required": true
}
]

这些参数与远程端点的需求一致。每个 API 端点都有不同的参数,因此它们需要是动态的。这是命令行的外观。

command run www.mysite.com/api/get -a testparam --bravo testpara2 -c item1 item2

参数和值将映射到 URL 中。有没有办法在点击中设置动态参数?

最佳答案

这可以通过构建一个自定义装饰器来完成,该装饰器在将给定的数据结构转换为点击等效项后多次调用 click.option 装饰器。

代码:

import click

def options_from_db(options):
map_to_types = dict(
array=str,
number=float,
string=str,
)
def decorator(f):
for opt_params in reversed(options):
param_decls = (
'-' + opt_params['short'],
'--' + opt_params['long'],
opt_params['name'])
attrs = dict(
required=opt_params['required'],
type=map_to_types.get(
opt_params['type'], opt_params['type'])
)
if opt_params['type'] == 'array':
attrs['cls'] = OptionEatAll
attrs['nargs'] = -1

click.option(*param_decls, **attrs)(f)
return f
return decorator

使用 options_from_db 装饰器:

要使用新的装饰器,请装饰命令,并从数据库传递选项数据,如下所示:

@options_from_db(run_options)
def command(*args, **kwargs):
....

这是如何工作的?

与所有装饰器一样,@click.option() 装饰器是一个函数。在这种情况下,它注释了修饰函数,并返回相同的函数。因此我们可以简单地多次调用它来注释我们的装饰函数。

注意:您的 array 参数违反了点击要求,不允许选项上出现 nargs < 0。但有another answer实现这一点,这个答案使用 the code从那里开始。

代码来自other answer :

class OptionEatAll(click.Option):

def __init__(self, *args, **kwargs):
self.save_other_options = kwargs.pop('save_other_options', True)
nargs = kwargs.pop('nargs', -1)
assert nargs == -1, 'nargs, if set, must be -1 not {}'.format(nargs)
super(OptionEatAll, self).__init__(*args, **kwargs)
self._previous_parser_process = None
self._eat_all_parser = None

def add_to_parser(self, parser, ctx):

def parser_process(value, state):
# method to hook to the parser.process
done = False
value = [value]
if self.save_other_options:
# grab everything up to the next option
while state.rargs and not done:
for prefix in self._eat_all_parser.prefixes:
if state.rargs[0].startswith(prefix):
done = True
if not done:
value.append(state.rargs.pop(0))
else:
# grab everything remaining
value += state.rargs
state.rargs[:] = []
value = tuple(value)

# call the actual process
self._previous_parser_process(value, state)

retval = super(OptionEatAll, self).add_to_parser(parser, ctx)
for name in self.opts:
our_parser = parser._long_opt.get(
name) or parser._short_opt.get(name)
if our_parser:
self._eat_all_parser = our_parser
self._previous_parser_process = our_parser.process
our_parser.process = parser_process
break
return retval

测试代码:

run_options = [
{
"name": "thename1",
"short": "a",
"long": "ace",
"type": "string",
"required": False
}, {
"name": "thename2",
"short": "b",
"long": "bravo",
"type": "number",
"required": True
}, {
"name": "thename3",
"short": "c",
"long": "candy",
"type": "array",
"required": True
}
]

@click.group()
def cli():
pass

@cli.command()
@options_from_db(run_options)
@click.argument('url')
def run(*args, **kwargs):
click.echo('args: {}'.format(args) )
click.echo('kwargs: {}'.format(kwargs))


if __name__ == "__main__":
commands = (
'run www.mysite.com/api/get -a testparam --bravo 5 -c item1 item2',
'',
'--help',
'run --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)
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)]
-----------
> run www.mysite.com/api/get -a testparam --bravo 5 -c item1 item2
args: ()
kwargs: {'thename1': 'testparam', 'thename2': 5.0, 'thename3': ('item1', 'item2'), 'url': 'www.mysite.com/api/get'}
-----------
>
Usage: test.py [OPTIONS] COMMAND [ARGS]...

Options:
--help Show this message and exit.

Commands:
run
-----------
> --help
Usage: test.py [OPTIONS] COMMAND [ARGS]...

Options:
--help Show this message and exit.

Commands:
run
-----------
> run --help
Usage: test.py run [OPTIONS] URL

Options:
-a, --ace TEXT
-b, --bravo FLOAT [required]
-c, --candy TEXT [required]
--help Show this message and exit.

关于python - 动态指定选项和参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50499340/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com