Tuple of strings parsed as string if one of the strings contains a hyphen
When parsing in a tuple of strings i can normally pass in comma-separated values with no issues, however if one of the values contains a hyphen the arguments gets parsed as a string instead of a tuple of strings.
Using your provided example.py script
import fire
fire.Fire(lambda obj: type(obj).__name__)
If i call it with multiple strings not containing hyphens i get the expected output
>>> python example.py '(foobar,baz)'
tuple
however, if I call it with a string containing a hyphen (-), I get this unexpected output
>>> python example.py '(foo-bar,baz)'
str
Is this to be expected? I also see that this is an issue with other symbols aswell. Is there a way to work around this other than to pass in a repr-like string?
E.g, this works, but is not very human friendly:
>>> python example.py '("foo-bar","baz")'
tuple
Edit: This is also the case for lists, sets and dicts containing strings.
Thanks for reporting; this is indeed a confusing experience.
As you've discovered, you can get the behavior you want with python example.py '("foo-bar","baz")', but as you note, it is not human friendly.
Part of the reason for this is that the outermost quotes in whatever command you run are processed by your shell.
This means that the seemingly logical python example.py ("foo-bar","baz") won't work either.
Is there a way to work around this other than to pass in a repr-like string? You could use the SetParseFn decorator to set your own arg parsing logic.
Now that we've dropped Python 2 support, we have the option of adding a feature for supporting type annotations to specify the parse function. Currently inputs are parsed based solely on their content, not based on the function expecting them. So this could improve the situation for functions annotated with arg: tuple[str]. We don't have active plans to add this feature either however.
My recommendation: If you're creating a CLI for other people to use, I recommend using @SetParseFn if you're accepting a sequence of strings. The current behavior of Fire is useful for if you're making a CLI (e.g. just for yourself) out of code you don't control, as it allows you to pass a sequence of strings if that's what's required, albeit sometimes requiring an uncomfortable syntax to do so.
The same happens on dict type. And what makes things worse is, on Windows, you have to use double quote in the outside and single quote inside:
"{'local':'en-US'}" # type: dict
'{"local":"en-US"}' # type str
The official example produces different results when executed on Windows and Linux
Execute under Linux:
$ python example.py '{"name": "David Bieber"}'
dict
$ python example.py {"name":'"David Bieber"'}
dict
$ python example.py {"name":"David Bieber"}
str
$ python example.py {"name": "David Bieber"}
error
$ python example.py '{"name": "Justin Bieber"}'
dict
Execute under Windows:
$ python example.py '{"name": "David Bieber"}'
error
$ python example.py {"name":'"David Bieber"'}
dict
$ python example.py {"name":"David Bieber"}
str
$ python example.py {"name": "David Bieber"}
error
$ python example.py '{"name": "Justin Bieber"}'
error
Do you suggest displaying these differences in Windows in the official documentation, or fixing the following to make Linux and Windows behave consistently?