typer icon indicating copy to clipboard operation
typer copied to clipboard

How to input an iterable as a required command-line option when prompted?

Open br-follow opened this issue 3 years ago • 3 comments

First Check

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

Commit to Help

  • [X] I commit to help with one of those options 👆

Example Code

import typer

app = typer.Typer()

@app.command()
def set_roles(
    single: str = typer.Option(..., prompt=True),
    multiple: list[str] = typer.Option(None, prompt=True),
):
    typer.echo(f"{single}")
    typer.echo(f"{multiple}")


if __name__ == "__main__":
    app()

Description

When I run the example without passing any arguments, I cannot pass multiple arguments to the prompt for multiple that satisfies the script. How must I format these at the prompt?

Example:

> python example.py
Single: one
Multple: one, two
Error: Value must be an iterable.
Multple: one two
Error: Value must be an iterable.
Multple: "one" "tow"
Error: Value must be an iterable.
Multple: "one,two"
Error: Value must be an iterable.
Multple: one
Error: Value must be an iterable.
Multple: one
Error: Value must be an iterable.
Multple: "one"
Error: Value must be an iterable.
Multple: [one, two]
Error: Value must be an iterable.
Multple: ["one", "two"]
Error: Value must be an iterable.
Multple: "['one','two']
Error: Value must be an iterable.

Operating System

macOS

Operating System Details

No response

Typer Version

0.4.0

Python Version

Python 3.10.1

Additional Context

No response

br-follow avatar Jan 09 '22 16:01 br-follow

Hey

Any update on that?

JeromeK13 avatar Aug 03 '22 11:08 JeromeK13

Any update?

Wyko avatar Aug 10 '22 13:08 Wyko

No Updates so far. One solutions I could think of is to use the rich implementation instead of the default click one. - Maybe this would work as expected and can handle the lists Just a thought - did not really played around with that yet

JeromeK13 avatar Aug 23 '22 07:08 JeromeK13

Also having this issue. Was trying to track down where the prompt is being generated from, and it may be underlying behaviour from Click

https://click.palletsprojects.com/en/8.0.x/options/#prompting

It is advised that prompt not be used in conjunction with the multiple flag set to True. Instead, prompt in the function interactively.

From some debugging - seems the source of the error is here.... https://github.com/pallets/click/blob/5e75fe7f9c1b820d71f482599cd6996523332d06/src/click/core.py#L2271

def check_iter(value: t.Any) -> t.Iterator:
    try:
        return _check_iter(value)
    except TypeError:
        # This should only happen when passing in args manually,
        # the parser should construct an iterable when parsing
        # the command line.
        raise BadParameter(
            _("Value must be an iterable."), ctx=ctx, param=self
        ) from None

def _check_iter(value: t.Any) -> t.Iterator[t.Any]:
    """Check if the value is iterable but not a string. Raises a type
    error, or return an iterator over the value.
    """
    if isinstance(value, str):
        raise TypeError

    return iter(value)

Seems that in the case of 'option with prompt' - seems like the arg will always come through as str and fail here.
I managed to use typer.prompt() to set a default of [] and convert to a list (for storage in a configparser file) using eval(input). - e.g. input the following on the command line...

['param1','param21','param3']

Not happy about it, as the input experience is brittle, and becomes 'interactive' by using typer.prompt - but it's functional. Would be good if more of Click's underlying functionality around types / specific parsers could be surfaced in Typer.

codebureau avatar Feb 01 '23 04:02 codebureau