创建一个 Click.Option 提示,仅当默认值为空时才显示

Creating a Click.Option with prompt that shows only if default value is empty

给定以下选项:

@cli.command()
@click.option('--param', default=lambda: get_value(), prompt="Enter Param")

正常行为是点击显示提示输入 param 的值并显示默认值(您可以通过它输入以保留默认值)。

相反,我希望 param 提示仅在 get_value() returns None 或某些预定义的 "show" 值时显示,但对于get_value() 单击的任何 Truthy/Other 值都不会显示此选项的提示和 运行 命令或移至下一个提示。

这可以通过覆盖 click.Option.get_default()click.Option.prompt_for_value() 方法来完成,例如:

自定义Class:

import click

class OptionPromptNull(click.Option):
    _value_key = '_default_val'

    def get_default(self, ctx):
        if not hasattr(self, self._value_key):
            default = super(OptionPromptNull, self).get_default(ctx)
            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

使用自定义 Class:

然后使用自定义 class,将其作为 cls 参数传递给选项装饰器,如:

@click.command()
@click.option('--param', cls=OptionPromptNull,
              default=lambda: get_value(), prompt="Enter Param")
def cli(param):
    click.echo("param: '{}'".format(param))

测试代码:

@click.command()
@click.option('--param1', cls=OptionPromptNull,
              default=lambda: get_value_none(), prompt="Enter Param1")
@click.option('--param2', cls=OptionPromptNull,
              default=lambda: get_value_one(), prompt="Enter Param2")
def cli(param1, param2):
    click.echo("param1: '{}'".format(param1))
    click.echo("param2: '{}'".format(param2))


def get_value_none():
    return None

def get_value_one():
    return 1

cli([])

结果:

Enter Param1: 23
param1: '23'
param2: '1'
class OptionPromptNull(click.Option):
    _value_key = '_default_val'

    def get_default(self, ctx):
        if not hasattr(self, self._value_key):
            default = super(OptionPromptNull, self).get_default(ctx)
            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.command()
@click.option('--tenant', '-t', cls=OptionPromptNull, default=Config.TENANT_NAME, prompt='Please enter tenant name', help='MindSphere tenant name')
@click.option('--client_id', '-ci', cls=OptionPromptNull, default=Config.CLIENT_ID, prompt='Please enter client id', help='MindSphere service account client id')
@click.option('--client_secret', '-cs', hide_input=True, cls=OptionPromptNull, default=Config.CLIENT_SECRET, prompt='Please enter client secret (it will be hidden while you type & kept secretly)', help='MindSphere service account client secret')
@click.option('--key', '-k', cls=OptionPromptNull, default=Config.ENCRYPTION_KEY, prompt='Please enter any secret key', help='Secret key used to store sensitive information in encrypted format ')
@click.option('--config_file', '-cf', cls=OptionPromptNull, default=Config.DEFAULT_CONFIG_FILE, prompt='Please enter config file path', help='Specific config file to execute MindSphere tasks')
def setup(tenant, client_id, client_secret, key, config_file):
    pass


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