Is there an equivalent to argparse
's nargs='*'
functionality for optional arguments in Click?
I am writing a command line script, and one of the options needs to be able to take an unlimited number of arguments, like:
foo --users alice bob charlie --bar baz
So users
would be ['alice', 'bob', 'charlie']
and bar
would be 'baz'
.
In argparse
, I can specify multiple optional arguments to collect all of the arguments that follow them by setting nargs='*'
.
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--users', nargs='*')
>>> parser.add_argument('--bar')
>>> parser.parse_args('--users alice bob charlie --bar baz'.split())
Namespace(bar='baz', users=['alice', 'bob', 'charlie'])
I know Click allows you to specify an argument to accept unlimited inputs by setting nargs=-1
, but when I try to set an optional argument's nargs
to -1, I get:
TypeError: Options cannot have nargs < 0
Is there a way to make Click accept an unspecified number of arguments for an option?
Update:
I need to be able to specify options after the option that takes unlimited arguments.
One way to approach what you are after is to inherit from click.Option, and customize the parser.
Custom Class:
Using Custom Class:
To use the custom class, pass the
cls
parameter to@click.option()
decorator like:or if it is desired that the option will eat the entire rest of the command line, not respecting other options:
How does this work?
This works because click is a well designed OO framework. The
@click.option()
decorator usually instantiates aclick.Option
object but allows this behavior to be over ridden with the cls parameter. So it is a relatively easy matter to inherit fromclick.Option
in our own class and over ride the desired methods.In this case we over ride
click.Option.add_to_parser()
and the monkey patch the parser so that we can eat more than one token if desired.Test Code:
Test Results:
I ran into the same issue. Instead of implementing a single command line option with n number of arguments, I decided to use multiple of the same command line option and just letting Click make a tuple out of the arguments under the hood. I ultimately figured if Click didn't support it, that decision was probably made for a good reason.
https://click.palletsprojects.com/en/7.x/options/#multiple-options
here is an example of what I am saying:
instead of passing a single string argument a splitting on a delimiter:
I opted to use this:
here is the source code:
This is more to type, but I do think it makes the CLI more user friendly and robust.
You can use this trick.
Add fake
option
with a needed name and none argumentsnargs=0
, then add 'argument' with the unlimited argsnargs=-1
.But be careful with the further options: