I'm writing a Python wrapper around another program. I want the user to be able to specify a few options for the wrapper and then pass the rest of the command-line through to the wrapped program. Something like this:
@click.command()
@click.option("--port", type=int)
@click.argument("args", nargs=-1)
def main(port, args):
call_the_wrapped_program(port=port, args=args)
But this dies with Error: no such option: -k because it treats any command-line switch as something it should parse rather than an argument that can be added to args.
Is this possible?
3 Answers 3
The Forwarding Unknown Options section in the documentation covers this use case. You should be able to write something like this:
@click.command(context_settings=dict(
ignore_unknown_options=True,
))
@click.option("--port", type=int)
@click.argument("args", nargs=-1, type=click.UNPROCESSED)
def main(port, args):
call_the_wrapped_program(port=port, args=args)
Comments
Assuming you invoke the program with something akin to a cli command, have you tried simply calling it like this?
cli --port 8080 -- -k arg1 arg2 -r etc
If I print args with that invocation, I get all the arguments out, albeit as a string, but I'm hoping that whatever third party you want to delegate to might be able to run its own parsing over that.
1 Comment
touch) a file through cli named "-k", then touch -k and touch "-k" and touch '-k' won't work. Instead, touch -- -k does work.Arguments should not have the - at start. By default anything starting with - is considered an option.
There is a way of parsing anything that doesn't fit your options set as an argument for this you will have to specify it:
@click.command(context_settings={"ignore_unknown_options": True})
@click.argument('args', nargs=-1)
def your function(args):
pass
You can find more in the docs.
But I doubt that this is what you want: it will parse -k as an argument, and the parameter that is after the -k as another argument.
I think what you really want is creating a command for each wrapped program separately, and specify options for each of them:
@click.group
def main(): pass
@main.command()
@click.option("--port", type=int)
@click.option('-k', '--key')
def your_wrapped_function(port, key):
pass
@main.command()
@click.option('--other-option')
def other_wrapped_function(other_option):
pass
Or maybe you wanted to add few parameters to the -k key, then use these docs:
@click.option('-k', nargs=-1)
The call to the function will be
cli your-wrapped-function 8080 -k arg1 arg2 argn
2 Comments
ssh and the idea of replicating all the options of ssh in the options to the wrapper is pretty unattractive.