Support for *args #1557
-
Describe the bugtyper fails for functions with *args in signature (variable number of arguments) To Reproduce
import typer
app = typer.Typer()
@app.command()
def hello(*names: str):
typer.echo(f"Hello {names}")
if __name__ == "__main__":
app()
python main.py alpha
Expected behaviorVariable number of arguments should be parsed as e.g done by ls, rm, cp and many other programs Environment
|
Beta Was this translation helpful? Give feedback.
Replies: 13 comments
-
|
@tiangolo, should this be a bug or a feature request? I would like to work on it if it's something that's being considered as an enhancement. |
Beta Was this translation helpful? Give feedback.
-
|
what happens if you change the type annotation from your type annotation is telling python / typer that I don't know if correcting the type annotation will fix the issue or not, but it's at least worth a shot |
Beta Was this translation helpful? Give feedback.
-
|
Not sure this is a bug since this isn't really supported by Typer docs as a way to get multiple values. If you wanted multiple values in a list, you would have to follow these guidelines this way. import typer
from typing import List
app = typer.Typer()
@app.command()
def hello(names: List[str]):
typer.echo(f"Hello {names}")
if __name__ == "__main__":
app()I think using unpacking for arguments would break the fundamental features of Typer, which is clearly stating the expecting types. |
Beta Was this translation helpful? Give feedback.
-
|
@daddycocoaman seems to work. However passing List[x] not just x as type hint contradicts the way it is defined in python PEPs. Mypy/pycharm/others should raise warnings on this code, see details here: |
Beta Was this translation helpful? Give feedback.
-
|
@arogozhnikov That's not the case at all. Generics like List are explicitly mentioned in accordance with PEP-484 |
Beta Was this translation helpful? Give feedback.
-
|
Correct example is given in your link, see section "Arbitrary argument lists and default argument values". *args can't be anything but list - it is senseless to specify that is it a list. |
Beta Was this translation helpful? Give feedback.
-
|
FYI, in a normal non-typed function, *args gets seen as a tuple of unknown length until defined, not a list. With typing like in your example, it gets recognized as Typer supports pretty clear Tuple and List classes, but in order for Typer to support an If you run So the change that would have to be made is that Typer would have to compare the parameter signatures to the |
Beta Was this translation helpful? Give feedback.
-
|
Thanks for a good summary.
You're correct, that's a tuple, thanks for correction. I am surprised it is not represented the right way by After your comment I understand source of this behavior in typer, but I consider it to be wrong, as it contradicts PEP examples. Mypy and pycharm seem to take care of *args typing the right way (i.e. they are PEP-compliant). Annotations like def f(*args: List[int])are treated as |
Beta Was this translation helpful? Give feedback.
-
|
I believe you can fairly easily determine whether a given argument is of the form >>> inspect.signature(my_func).parameters['args'].kind
<_ParameterKind.VAR_POSITIONAL: 2>You will unfortunately need to do more than just change the type from X to I don't know what @arogozhnikov had in mind with this request, but I'm trying to make a subcommand that can pass arbitrary arguments to another shell command, after removing any initial options, much like e.g. def main(*args: str, myparam: bool = False):
...The command Is that possible to support with Click (and hence to hook up in Typer for Edit: I hope this hasn't come across as demanding this feature — wanted to know if it was even possible before talking about whether it might be a thing you'd be interested in adding. |
Beta Was this translation helpful? Give feedback.
-
|
@alicederyn did you find a way to forward arguments/options? def forwarder(name: str, forwards: str):
...and have the def forwarder(name: str, forwards: List[str]):
forwards = recombine(forwards)
...This still fails on options though since |
Beta Was this translation helpful? Give feedback.
-
|
@Bonnevie no, I gave up trying to migrate from docopt after hitting this issue, it wasn't worth the investment for the tool I was looking at |
Beta Was this translation helpful? Give feedback.
-
|
I tend to agree with @daddycocoaman that this is no bug, and quite reasonable behaviour. It looks like support could be added for |
Beta Was this translation helpful? Give feedback.
-
|
This is definitely not a bug (Typer hasn't claimed the support for this). As for adding this support - as it was already mentioned, we can already declare arguments that accept multiple values in a different way. If the point is to make this function reusable without Typer, then I think you can add a thin wrapper that accepts |
Beta Was this translation helpful? Give feedback.
This is definitely not a bug (Typer hasn't claimed the support for this).
As for adding this support - as it was already mentioned, we can already declare arguments that accept multiple values in a different way.
If the point is to make this function reusable without Typer, then I think you can add a thin wrapper that accepts
*argsand passes them as list to the wrapped function