typer icon indicating copy to clipboard operation
typer copied to clipboard

DOC: Documentation of passing multiple values in "option" vs "argument" isn't sufficiently explicit

Open corneliusroemer opened this issue 2 years ago • 8 comments

Privileged issue

  • [X] I'm @tiangolo or he asked me directly to create an issue here.

Issue Content

I was looking into passing multiple (N>=1, all N >=1 allowed) white space separated values via an option.

This does not seem possible at the moment, but the documentation wasn't very clear. It's only possible to pass an exact number of space separated values via an option, but not a list: https://typer.tiangolo.com/tutorial/multiple-values/options-with-multiple-values/

Multiple values are only possible via argument, yet the documentation for the two types reads almost identical (at least the first few paragraphs): https://typer.tiangolo.com/tutorial/multiple-values/arguments-with-multiple-values/

It would be good to be precise in the first paragraph about the fact that options don't allow you to pass N>=1 values.

Maybe one could accept multiple values by specifying a separator that's not white space, like comma-separated - but that's a feature request in a bit different direction.

corneliusroemer avatar Feb 14 '23 17:02 corneliusroemer

I just encountered this issue too. This is definitely a feature I'd absolutely love to have (white space or comma separated lists)

I'm really not a fan of having to re-write the commands like --command val1 --command val2

Either

--command val1 val2 or --command val1,val2 would be such a big feature for me.

Not sure where to put in a request for this, or if its been stated that it is not going to be implemented!

Thanks so much to all contributers of this repo anyhow, found it a few days ago and switched all my CLI workflows to it almost immediately! Love it!

shanilpanara avatar Mar 13 '24 10:03 shanilpanara

I see that the PR is passing and has been accepted. Any idea when this will be merged? I currently implement this via a workaround in my code, but this would allow for much cleaner implementation while using the library.

alsidneio avatar Jun 06 '24 17:06 alsidneio

Hey there,

I coded a quick workaround for the "Typer doesn't support whitespace-separated multi-value options" (sorry won't have time for a PR) after moving from argparse to typer for a big project.

My users are used to running 'app some_command --filters filter1 filter2 filter3 --envs env1 env2 env3' and I thought using 'app some_command --filters filter1 --filters filter2 --filters filter3 --envs env1 --envs env2 --envs env3' would be too much of a gap/pain for them and I, so I simply wrote a quick function that preprocesses the sysargv from whitespace-separated multi-value options to the typer format before they're given to typer.

For anyone who needs it as well:

def preprocess_args():
    """
    Typer doesn't support whitespace-separated multi-value options.

    We preprocess the sysargv so that:
    - python3 app.py some_command --filters filter1 filter2 filter3 --environments env1 env2 env3

    becomes:
    - python3 app.py some_command --filters filter1 --filters filter2 --filters filter3 --environments env1 --environments env2 --environments env3

    //!\\ DOWNSIDE: options should always be after arguments in the CLI command //!\\
    """

    logger.debug(f"Initial CLI command is: {sys.argv}")

    # get main cmd
    final_cmd = []
    for idx, arg in enumerate(sys.argv):
        if any(arg.startswith(_) for _ in ['-', '--']):
            break
        else:
            final_cmd.append(arg)
    logger.debug(f"Main command is: {final_cmd}")

    # get options and their values
    for idx, arg in enumerate(sys.argv):
        if any(arg.startswith(_) for _ in ['-', '--']):
            opt_values = [] 
            for value in sys.argv[idx+1:]:
                if any(value.startswith(_) for _ in ['-', '--']):
                    break
                else:
                    opt_values.append(value)
            
            if len(opt_values) >= 1:
                [final_cmd.extend([arg, opt_value]) for opt_value in opt_values]
            else:
                final_cmd.append(arg)

    # replace by reformatted
    logger.debug(f"Final command is: {final_cmd}")
    sys.argv = final_cmd
    

if __name__ == "__main__":
    preprocess_args()
    app()

Note that the sysargv preprocessing above won't be taken into account in your test files if you use the typer.testing CliRunner, so in your tests you'll have to use the typer format instead.

Happy long weekend to all of you

DvdNss avatar Sep 01 '24 05:09 DvdNss

Hi @DvdNss,

thanks for the contribution! I think that the original reason for not supporting this is, as you've already pointed out in the comment of your code, that this forces arguments to be specified before options on the command line to avoid potential ambiguity between arguments and options. A similar issue has been raised in click: https://github.com/pallets/click/issues/2537. I am unsure whether this functionality is desired in typer @svlandeg.

libklein avatar Sep 02 '24 21:09 libklein

Note to solve the potential ambiguity issue, there is a widely used convention (e.g. by git, and gnu tools) for an optional double dash -- to separate options from parameters.

See e.g. https://www.gnu.org/prep/standards/html_node/Command_002dLine-Interfaces.html

peterjc avatar Oct 11 '24 14:10 peterjc

It seems the Python standard library supports this:

https://docs.python.org/3/library/argparse.html#nargs

I think Typer really should too.

valankar avatar Mar 30 '25 09:03 valankar

Note that, users can write --filters={filter1,filter2,filter3} if they are calling from shell (not execv-style function) which will be expanded to the version that typer accepts by the shell

AlexeyDmitriev avatar Jun 06 '25 08:06 AlexeyDmitriev

Seems that current version of docs is quite explicit about this:

CLI Options with Multiple Values

CLI Options with Multiple Values

You can also declare a CLI option that takes several values of different types.

You can set the number of values and types to anything you want, but it has to be a fixed number of values

YuriiMotov avatar Sep 12 '25 13:09 YuriiMotov