The simplest solution is basically the same thing you'd do with a regular Python function where you wanted an API like this.
Take a single parameter that groups the variable-length stream of arguments into a tuple. Then, what you do depends on whether you want separate arguments:
>>> def func(*args):
... d = dict(zip(args[::2], args[1::2]))
... print(d)
>>> func('FOO', 1, 'BAR', 2)
{'FOO': 1, 'BAR': 2}
… or combined key:value arguments:
>>> def func(*args):
... d = dict(arg.split(':') for arg in args)
... print(d)
This one is a bit hacky to use, because in Python, arguments aren't just space-separated words, but bear with me on that:
>>> func('FOO:1', 'BAR:2')
{'FOO': 1, 'BAR': 2}
The click equivalent for the first looks like this:
@click.command()
@click.argument('args', nargs=-1)
def my_command(args):
d = dict(zip(args[::2], args[1::2]))
click.echo(d)
(Obviously you can stick that in a click.group, etc., just like any other command.)
And now:
$ ./clicky.py FOO 1 BAR 2
{'FOO': 1, 'BAR': 2}
And the second looks like this:
@click.command()
@click.argument('args', nargs=-1)
def my_command(args):
d = dict(arg.split(':') for arg in args)
click.echo(d)
And notice that now, using it is not hacky at all, because to your shell, arguments are just words separated by spaces:
$ ./clicky.py FOO:1 BAR:2
{'FOO': 1, 'BAR': 2}
What if you want to handle both KEY=VALUE and KEY:VALUE? Then you just have to write something slightly more complicated than arg.split(':'). And you'll probably want some better error handling too. But that should be enough to get you started.
my_commandwill get them all as a single tuple (like*argsin regular Python) and iterate over them and pair them up?--foo=1,--foo:1,--foo 1, but need arbitrary option-like-things and without--prefixes—then I think it's impossible. You could write a newParametersubclass that handles these, but that's explicitly not supported, and may be broken by even minor updates toclick.dd-style operands", and come up with other common examples that are equivalent to what you want, both to make your request seem more useful/normal, and to provide a good test case if someone does decide to implement it.