Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

unlimited argument for an option with comma spliter #534

Open
7 tasks done
Alirezaaraby opened this issue Jan 15, 2023 · 2 comments
Open
7 tasks done

unlimited argument for an option with comma spliter #534

Alirezaaraby opened this issue Jan 15, 2023 · 2 comments
Labels
question Question or problem

Comments

@Alirezaaraby
Copy link

First Check

  • I added a very descriptive title to this issue.
  • I used the GitHub search to find a similar issue and didn't find it.
  • I searched the Typer documentation, with the integrated search.
  • I already searched in Google "How to X in Typer" and didn't find any information.
  • I already read and followed all the tutorial in the docs and didn't find an answer.
  • I already checked if it is not related to Typer but to Click.

Commit to Help

  • I commit to help with one of those options 👆

Example Code

import typer

def main(command: List[str] = typer.Option(None)):
    print(command)

Description

I want to pass unlimited multiple arguments to type.option with comma splitter like below.

$ python cli.py add test -C "hi I'm test", "hello this is test"

I want to get a list like ["hi I'm test","hello this is test"] from the above input.

Operating System

Windows

Operating System Details

Windows Version 10.0.19045.2486

Typer Version

0.7.0

Python Version

Python 3.9.1

Additional Context

No response

@Alirezaaraby Alirezaaraby added the question Question or problem label Jan 15, 2023
@heiskane
Copy link

As far as i understand the intended way to use a list type parameter would be like this:

$ python app.py --command arg1 --command arg2
['arg1', 'arg2']

If you really want to use comma separated strings you could do the following:

from typing import Annotated

import typer

def comma_list(raw: str) -> list[str]:
    return raw.split(",")


def main(
    command: Annotated[list, typer.Option(parser=comma_list)],
):
    print(command)


if __name__ == "__main__":
    typer.run(main)
$ python potato/main.py --command "hello","world"
['hello', 'world']

Note that using list[str] instead of list for the command parameter seems to attempt some type conversion magic resulting in a nested list so this isn't perfect. Personally I would just keep it simple and do something like this instead:

import typer


def main(commands: str = typer.Option()):
    cmd_list = commands.split(",")
    print(cmd_list)


if __name__ == "__main__":
    typer.run(main)

@devraj
Copy link

devraj commented Jul 11, 2024

I implemented something quite similar in my cli where it takes multiple values as part of an argument in a standard unix fashion i.e separated by spaces.

Essentially extending on what @heiskane is suggesting you do for Option you can define an argument as follows:

from typing import Optional, List
from typing_extensions import Annotated

import typer

@app.command("ack")
async def acknowledge(
    ids: Annotated[List[int], typer.Argument(help="alarm id")], #multiple ids
    message: Annotated[
        Optional[str],
        typer.Option(
            "-m",
            "--message",
            help="comment to add to history",
        ),
    ] = None,
):
    for id in ids:
        print(id)

See issue on my project for more detail.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Question or problem
Projects
None yet
Development

No branches or pull requests

3 participants