2

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?

asked Feb 28, 2022 at 13:55

3 Answers 3

5

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)
answered Jun 15, 2022 at 4:43
Sign up to request clarification or add additional context in comments.

Comments

2

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.

answered Mar 1, 2022 at 20:53

1 Comment

I think the comment above is according to conventions. If you would like to create (touch) a file through cli named "-k", then touch -k and touch "-k" and touch '-k' won't work. Instead, touch -- -k does work.
0

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
answered Sep 5, 2024 at 9:33

2 Comments

I kind of get where you're going with this, but the wrapped program is ssh and the idea of replicating all the options of ssh in the options to the wrapper is pretty unattractive.
Oh! I didn't think about such case :). Googling a bit I found this ( stackoverflow.com/questions/32944131/… ) topic. Check the accepted answer there. I think it looks the best.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.