Reputation: 140
I'm just starting out with a simple project and using the Click library and have hit a snag early on that I can't figure out. When I run this with the "--testmode" flag it shows as True however the subsequent function doesn't execute and I get an error that no such option is defined? What am I doing wrong here?
import click
@click.command()
@click.option('--user', prompt=True)
@click.option('--password', prompt=True, hide_input=True, confirmation_prompt=False)
def authenticate(user, password):
pass
@click.command()
@click.option('--age')
@click.option('--testmode', is_flag=True)
def main(age, testmode):
print('Age: ', age)
print('Testmode: ', testmode)
if testmode:
authenticate()
if __name__ == "__main__":
main()
Console output:
python .\dev.py --help
Usage: dev.py [OPTIONS]
Options:
--age TEXT
--testmode
--help Show this message and exit.
python .\dev.py --testmode
Age: None
Testmode: True
Usage: dev.py [OPTIONS]
Try 'dev.py --help' for help.
Error: no such option: --testmode
Upvotes: 0
Views: 3016
Reputation: 354
I had same error, but with a different cause. Posting for others who may run into it.
I was running myscript.py -?
and getting the message error: no such option: -o
. Very confusing, I entered one option (-?
) which exists, but it complained about a different one (-o
). Checked my environment, imports, even thought optparse library may have been corrupted.
Turns out I (somehow, mistakenly) had a file named -o
in current dir. So bash was turning -?
into -o
and passing it to my script. SMH. Always check your fileystem!
Upvotes: 0
Reputation: 2781
Iarsks answer is what you're looking for, but to elaborate on that further, the Click documentation has some information on invoking other commands. So if you really wanted authenticate
to be setup as a command, you have 2 options.
Abstract the logic from authenticate
into a python method, and invoke that inside authenticate
and the if testmode
block.
Look into invoking one command from another. Click commands have access to a context, which is a way for click to hold state referring to the current command, and other commands. More information can be found here.
For clarity, a click context ctx
can invoke another command as such:
ctx.invoke(authenticate, user=user_value, password=password_value)
.
If the current command that was invoke has the same options and parameters as the other one you'd like to invoke, click offers a shorthand for it:
click.forward(authenticate)
, which will pass the same arguments to the authenticate
command.
Upvotes: 1
Reputation: 311556
The problem is here:
if testmode:
authenticate()
You're calling authenticate()
like a function, but you've defined it as another click.command
. That means it's going to look at sys.argv
for command line options, find --testmode
, and compare that against the options you defined with @click.option
.
The authenticate
method doesn't have a --testmode
option, hence the error you're seeing.
There are various ways to fix this. Does authenticate
really need to be configured as a command? The way you've got your code set up right now there's no way to call it via the command line.
Upvotes: 3