python - 单击 - 基于其他选项的提示的动态默认值

标签 python python-click

我正在使用 Click构建 CLI 界面。点击优惠dynamic defaults for prompts ,这很棒。还有 this example给出了一些关于如何使用自定义点击类实现动态默认值的见解,从而在评估默认值时提供更灵活的选项。

我现在想做的是根据另一个提供的点击选项获得动态默认值,例如

python mymodule --param1 something --param2 somethingelse

现在,如果 param2 为空,我想尝试根据提供的 param1 输入获取动态默认值,例如:

@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

关于什么是完成这项工作的最佳方式有什么想法吗? 是否保证 param1param2 之前被评估(并提示)?

最佳答案

扩展example you referenced所需的功能可以像这样完成:

###自定义类:

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, **kwargs):
        if not hasattr(self, self._value_key):
            if self.default_option is None:
                default = super(OptionPromptNull, self).get_default(ctx, **kwargs)
            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 装饰器,例如:

@click.option('--param3', cls=OptionPromptNull, default_option='param1',
              default=lambda x: get_a_value(x), prompt="Enter Param3")
  • cls 需要引用自定义类。

  • default_option 需要指定将哪个选项传递给 default 可调用对象。

  • default 指定用于获取默认值的可调用对象。

###这是如何工作的?

之所以可行,是因为 click 是一个设计良好的 OO 框架。 @click.option() 装饰器通常实例化一个 click.Option 对象,但允许使用 cls 参数覆盖此行为。因此,在我们自己的类中继承 click.Option 并覆盖所需的方法是一件相对容易的事情。

在本例中,我们覆盖了 click.Option.get_default()click.Option.prompt_for_value() 方法。在 prompt_for_value() 中,我们仅在默认值为 None 时提示。然后在 get_default() 中,我们调用 default 函数传递所需的(先前输入的)参数。

为了澄清问题的一部分,首先评估选项:按照它们在命令行上传递的顺序,其次:按照它们为那些未在命令行上传递的选项声明的顺序。

###测试代码:

@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.

关于python - 单击 - 基于其他选项的提示的动态默认值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51846634/

相关文章:

python - 表面图 : Add legend to facecolors

python click 应用程序失败并显示 "missing argument"但无法找到问题

python - 将零个或可变数量的值传递给 Click.Option

python-3.x - 这个 python-click 行为正确吗?

python - 如何使用 Python 的 click (Command Line Interface Creation Kit) 包将变量传递给其他方法

python - 在 azure 上部署训练有素的 python 数据科学项目作为服务

python - 使用 matplotlib 在 Python 中未显示绘图

python - 如何用天数计算注释 Django 查询?

python - 如何通过继承有效地使用鸭子类型(duck typing)

python - Click 退出时退出代码为 2 是什么意思?