单击-基于其他选项的提示动态默认值 [英] Click - Dynamic Defaults for Prompts based on other options
问题描述
我正在使用单击来构建CLI界面.单击提供的提示的动态默认值,非常好.另外,此示例给出了一些有关如何使用自定义点击类实现动态默认设置的见解,从而在评估时提供了更灵活的选项默认值.
I'm using Click to build a CLI interface. Click offers dynamic defaults for prompts, which is great. Also this example gives some insights on how to implement dynamic defaults using a custom click-class and thus provide more flexible options when evaluating the default value.
我现在要做的是根据另一个提供的点击选项(例如,
What I'm trying to do now is to have dynamic defaults based on another provided click option, e.g.
python mymodule --param1 something --param2 somethingelse
现在,如果param2
为空,我想尝试根据提供的param1
输入获得动态默认值,例如:
Now if param2
is empty I want to try to get a dynamic default based on the provided param1
input, e.g.:
@click.command()
@click.option('--param1', prompt=True)
@click.option('--param2', prompt=True, default=lambda: myfunct(param1))
def cmd(param1, param2):
pass
myfunct(param1:str=None):
param2 = None
#get param2 based on param1 input
return param2
关于完成这项工作的最佳方法的任何想法?
并保证在param2
之前先评估(并提示)param1
吗?
Any ideas on what would be the best way to get that done?
And is it guaranteed that param1
is evaluated (and prompted for) before param2
?
推荐答案
扩展您引用的示例所需的功能可以像这样完成:
Extending the example you referenced the desired functionality can be done like:
import click
class OptionPromptNull(click.Option):
_value_key = '_default_val'
def __init__(self, *args, **kwargs):
self.default_option = kwargs.pop('default_option', None)
super(OptionPromptNull, self).__init__(*args, **kwargs)
def get_default(self, ctx):
if not hasattr(self, self._value_key):
if self.default_option is None:
default = super(OptionPromptNull, self).get_default(ctx)
else:
arg = ctx.params[self.default_option]
default = self.type_cast_value(ctx, self.default(arg))
setattr(self, self._value_key, default)
return getattr(self, self._value_key)
def prompt_for_value(self, ctx):
default = self.get_default(ctx)
# only prompt if the default value is None
if default is None:
return super(OptionPromptNull, self).prompt_for_value(ctx)
return default
使用自定义类:
要使用自定义类,您需要将三个参数传递给click.option
装饰器,例如:
Using the Custom Class:
To use the custom class you need to pass three parameters to the click.option
decorator like:
@click.option('--param3', cls=OptionPromptNull, default_option='param1',
default=lambda x: get_a_value(x), prompt="Enter Param3")
-
cls
需要引用自定义类.cls
need to reference the custom class.default_option
需要指定哪个选项将传递给default
可调用对象.default_option
needs to specify which option will be passed to thedefault
callable.default
指定用于获取默认值的可调用对象.default
specifies the callable used to get the default.之所以可行,是因为
click
是一个设计良好的OO框架.@click.option()
装饰器通常会实例化click.Option
对象,但允许使用cls
参数覆盖此行为.因此,在我们自己的类中从click.Option
继承并超越所需的方法是相对容易的事情.This works because
click
is a well designed OO framework. The@click.option()
decorator usually instantiates aclick.Option
object but allows this behavior to be over ridden with thecls
parameter. So it is a relatively easy matter to inherit fromclick.Option
in our own class and over ride desired methods.在这种情况下,我们超越了
click.Option.get_default()
和click.Option.prompt_for_value()
方法.在prompt_for_value()
中,我们仅提示默认值为None
.然后在get_default()
中,我们调用default
函数,以传递所需的(先前输入的)参数.In this case we over ride the
click.Option.get_default()
and theclick.Option.prompt_for_value()
methods. Inprompt_for_value()
we only prompt if the default isNone
. And then inget_default()
we call thedefault
function passing the desired (previously entered) param.为阐明问题的一部分,首先评估选项:按在命令行上传递的顺序,然后对选项进行评估:对于未在命令行上传递的选项,按声明的顺序进行./p>
测试代码:
And to clarify one part of the question, the options are evaluated first: in the order they were passed on the command line, and second: in the order they were declared for those that were not passed on the command line.
@click.command() @click.option('--param1', prompt="Enter Param1") @click.option('--param2', cls=OptionPromptNull, default=lambda: get_value_none(), prompt="Enter Param2") @click.option('--param3', cls=OptionPromptNull, default_option='param1', default=lambda x: get_a_value(x), prompt="Enter Param3") def cli(param1, param2, param3): click.echo("param1: '{}'".format(param1)) click.echo("param2: '{}'".format(param2)) click.echo("param3: '{}'".format(param3)) def get_value_none(): return None def get_a_value(val): return val if __name__ == "__main__": commands = ( r'', r'--param3 5', '--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)] ----------- > Enter Param1: 3 Enter Param2: 4 param1: '3' param2: '4' param3: '3' ----------- > --param3 5 Enter Param1: 3 Enter Param2: 4 param1: '3' param2: '4' param3: '5' ----------- > --help Usage: test.py [OPTIONS] Options: --param1 TEXT --param2 TEXT --param3 TEXT --help Show this message and exit.
这篇关于单击-基于其他选项的提示动态默认值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!