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

2

2

Given the following option:

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

Normal behavior is for click to show a prompt to enter a value for param and display the default value (and you can just ENTER through it to preserve that).

Instead I'd like the param prompt to only show if get_value() returns None or some pre-defined "show" value, but for any Truthy/Other value for get_value() click will not show the prompt for this option and run the command or move to the next prompt.

Putrefaction answered 24/8, 2017 at 18:24 Comment(0)
C
3

This can be done by over riding the click.Option.get_default() and the click.Option.prompt_for_value() methods like:

Custom 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

Using Custom Class:

Then to use the custom class, pass it as the cls argument to the option decorator like:

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

Test Code:

@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([])

Result:

Enter Param1: 23
param1: '23'
param2: '1'
Crenulate answered 24/8, 2017 at 20:25 Comment(4)
Sorry for the delay, missed the notification on the answer somehow, works great!Putrefaction
What if get_value_one() requires a import that is another param? e.g. get_value_one(otherclickparam)?Danieladaniele
You want the get_value_one() to be evaluated with another (prior) parameter? That sounds like a great question! I would imagine it is doable, but will be more involved than the above. You should write up a new question. If you like, you can leave a comment here with link to that question so I am sure to see it.Crenulate
Yep. That's what I'm looking for. Posted a question here: #51847134Danieladaniele
A
-3
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

Usage:

@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

Aric answered 9/1, 2019 at 7:3 Comment(1)
Hi Dinesh, any reason why you duplicated the answer above? literally using the same code. Please note also that the answer has already been answered. If you have anything to add, please do so in a comment on the original answerPutrefaction

© 2022 - 2024 — McMap. All rights reserved.