Reputation: 18438
I have built a command line interface using Python's click library (version 7.1.2) that can run a command that asks the (human) user to answer certain confirmations on the way (The well known "Are you sure you want to continue? Y/n"
)
Now, I'm trying to run that command automatically on a Kubernetes CronJob and I need a way of "pretending" to input Y
to each of the prompts.
I have seen the click.confirmation_option
, but if I understand correctly, that seems more like a confirmation to run the whole command, right? (maybe I'm wrong?)
I'm more looking for something like some kind of assume_yes
in the example below (could be passed either to the invocation or when creating full context ctx = cli.make_context...
):
from my_command import cli
ctx = cli.make_context(
'main_command_group', ["action", "--num_times", 3]
)
with ctx:
result = cli.invoke(ctx, assume_yes=True)
Is that possible?
I can always add some kind of environment variable, or pass an extra boolean Option (a flag) to my Click command and edit my code so before even trying to show the confirmation prompt, it'd check whether the environment variable (or the flag) is True
, and if so, then assume yes (without even showing the prompt), but it feels like Click
must have something for unattended runs.
EDIT: (As per the comments)
The prompts look like:
customer = CustomerManager.get_by_name(customer_name)
if (
not customer and
click.confirm(f"Create customer {customer_name}", default=True)
):
customer = CustomerManger.create(name=customer_name)
# more code
if not customer.address:
if click.confirm(
f"No address for customer {customer.name}. Leave blank?",
default=True):
# ...
As to why doing it this way: Because the exact same code is going to be run first by humans (as a script... on the command line) and once the human user "ok"s it, it will be pushed to a pod where it'll be run by a CronJob.
Running the script on the command line will populate a local database, run some data checks, some verifications... So once everything is confirmed to be "good" locally by a human, a signal will be sent to a Kubernetes Cronjob that will do exactly the same as the humans. The only difference is that at that point it can assume the answer to all the prompts is "yes".
So yes: the code could be refactored, but it would be nice if it didn't have to be (because when the CLI is run by the cronjob, we already know that the answer to every confirmation prompt is going to be a "yes")
Upvotes: 0
Views: 2614
Reputation: 989
OK, if you want to do this globally, and not per command, you may override easily the confirm() behaviour:
def confirm(*args, **kwargs):
if not os.environ.get('yes'):
click.confirm(*args, **kwargs)
And than, you could use your local version of confirm
, instead of click.confirm
in your code:
@click.command()
def test():
confirm('Create customer', default=False, abort=True)
...
Now, if you export the yes
environment variable, you will see the difference.
Upvotes: 1
Reputation: 989
How do you expect from Click_ to handle this out of the box? The system needs to know that you are a robot, and not a human. How could you achieve this? One way is to have some environment variable, another way is to use special API for your cron job. Nevertheless – you will end up with a special option for this case.
You are totally right – the confirmation_option doesn't cover your case, but it shows you how are you supposed to handle such cases.
So, what I would do is something like this:
@click.option('--yes', is_flag=True)
def my_method(customer_name, yes):
if not yes:
click.confirm(f"Create customer {customer_name}", default=False, abort=True)
customer = CustomerManger.create(name=customer_name)
You could use environment variables, but I don't see any reason to do it. You can force your cron job to provide the --yes option. It is easier and more obvious.
I played around with the abort=True here, because otherwise I need to repeat the create line one more time, but it may not be suitable for you, if you don't want to abort the whole command and just want to skip the creation of the customer.
And something not related to your question: I advise you to default to False (this is how Click_ works by default), instead of True in your confirmation. I could hit enter unintentionally and shoot myself in the foot. You won't have confirmation dialogue if it wasn't dangerous to confirm bad data, so better don't easy the confirmation that way :)
Upvotes: 1