Closed Wooza closed 4 years ago
Thanks a lot for opening this issue! Let me test things out and think about it for a few days and I'll get back to you.
Hey @Wooza, out of curiosity, in your context is the number of flags used completely arbitrary? Could you give me a bit more detail about some scenarios where you think this could be useful?
For instance this is what is currently supported:
import enum
from dataclasses import dataclass
from typing import List, Tuple
from simple_parsing import ArgumentParser, list_field, field
class Color(enum.Enum):
RED = "RED"
ORANGE = "ORANGE"
BLUE = "BLUE"
MAGENTA = "MAGENTA"
@dataclass
class MyPreferences:
"""You can use Enums"""
color: Color = Color.BLUE # my favorite colour
# A list of colors I hate.
hated_colors: List[Color] = list_field(Color.MAGENTA, Color.ORANGE)
parser = ArgumentParser()
parser.add_arguments(MyPreferences, "my_preferences")
args = parser.parse_args()
prefs: MyPreferences = args.my_preferences
print(prefs)
Executing this with the "--help flag":
python .\examples\enums\enums_example.py --help
usage: enums_example.py [-h] [--color {RED,ORANGE,BLUE,MAGENTA}] [--hated_colors [Color [Color ...]]]
optional arguments:
-h, --help show this help message and exit
MyPreferences ['my_preferences']:
You can use Enums
--color {RED,ORANGE,BLUE,MAGENTA}
my favorite colour (default: BLUE)
--hated_colors [Color [Color ...]]
A list of colors I hate. (default: [<Color.MAGENTA: 'MAGENTA'>, <Color.ORANGE: 'ORANGE'>])
As you can see, the help string defaults for enums are quite ugly. I was able to achieve the kind of formatting I think you're describing with this:
@dataclass
class MyPreferences:
"""You can use Enums"""
color: Color = Color.BLUE # my favorite colour
# A list of colors I hate.
hated_colors: List[Color] = list_field(
Color.MAGENTA, Color.ORANGE, # the default values
choices=[e.name for e in Color], # the available values
)
which gives:
python .\examples\enums\enums_example.py --help
usage: enums_example.py [-h] [--color {RED,ORANGE,BLUE,MAGENTA}] [--hated_colors [{RED,ORANGE,BLUE,MAGENTA} [{RED,ORANGE,BLUE,MAGENTA} ...]]]
optional arguments:
-h, --help show this help message and exit
MyPreferences ['my_preferences']:
You can use Enums
--color {RED,ORANGE,BLUE,MAGENTA}
my favorite colour (default: BLUE)
--hated_colors [{RED,ORANGE,BLUE,MAGENTA} [{RED,ORANGE,BLUE,MAGENTA} ...]]
A list of colors I hate. (default: [<Color.MAGENTA: 'MAGENTA'>, <Color.ORANGE: 'ORANGE'>])
However this doesn't currently work (apart from the "--help" option), as its impossible to parse the values:
python .\examples\enums\enums_example.py --hated_colors ORANGE RED
usage: enums_example.py [-h] [--color {RED,ORANGE,BLUE,MAGENTA}] [--hated_colors [{RED,ORANGE,BLUE,MAGENTA} [{RED,ORANGE,BLUE,MAGENTA} ...]]]
enums_example.py: error: argument --hated_colors: invalid choice: <Color.ORANGE: 'ORANGE'> (choose from 'RED', 'ORANGE', 'BLUE', 'MAGENTA')
Also, for the help string formatting, you could also easily do this, which would totally work! (you'd lose the auto-generated help strings and would have to add it manually to the help
argument though):
@dataclass
class MyPreferences:
"""You can use Enums"""
color: Color = Color.BLUE # my favorite colour
# A list of colors I hate.
hated_colors: List[Color] = list_field(
Color.MAGENTA, Color.ORANGE, # the default values, if any.
help=f"Some Colors I hate. (Possible: {set(e.name for e in Color)})",
)
Which would get you what you want, in the end:
(...)
--hated_colors [Color [Color ...]]
Some Colors I hate. (Possible: {'BLUE', 'RED', 'MAGENTA', 'ORANGE'}) (default: [<Color.MAGENTA: 'MAGENTA'>, <Color.ORANGE: 'ORANGE'>])
This sounds like the best option, in my opinion. Let me know what you think.
Hey @lebrice, thanks for your fast feedback and effort. The amount of flags is around 20 to 30. I think your solution with manually specifying the help string is ok, since it can be automatically generated. I only have to work out how to deal with the line breaks, to avoid a single long line. I'll close this issue and might reopen it, if I stumble into any further problems 😄
What are those 20-30 flags used for? Also, you can use the backslash \ to spread your command onto many lines.
We have a program with different genetic algortihms and an enum which defines different aspects that we want to track while an algorithm is running, e.g. best current fitness or number of generations.
When we run an evaluation, we don't always need all of those values, so we specify the values which should be tracked/output by using a field with List[Enum] ...
.
Thanks for the \
tip.
Is your feature request related to a problem? Please describe. I'd like to be able to pass a list of flags to my program. The flags are all listed in an enum and the variable in the dataclass is defined as
flags: List[MyEnum] = ...
Argument parsing works, but no proper help text is generated.Describe the solution you'd like If the argument of the List annotation has a finite amount of possible values (e.g. enum values), it would be nice to list those. This is already done, when a field is directly annotated as an enum.
Possible output:
Although I'm not sure, where/how the values should be listed
Describe alternatives you've considered I could manually update the help text when the enum values change, but that violates the DRY principle.