Open fennerm opened 6 months ago
Hi @fennerm, I'm not against a PR, I'd just like to discuss this further, because honestly I don't understand the issue here 🤔 Using the key in my opinion is arguably more intuitive, since its value could be arbitrarily more complex. As far as I understand, in argdantic enums are used without any particular difference from pydantic: at their core they are basically a fancier dict, so the cli uses the key to retrieve the actual enum item and returns that.
I honestly fail to see the problem, except for the character limit. Also, if I understood correctly, and you'd like to use the values as cli choice, literals should already be a good fit for this, probably.
Hey @edornd as far as I'm aware pydantic does indeed use the enum value, here's an example:
from enum import Enum
from pydantic import BaseModel
class MyEnum(Enum):
KEY = "value"
class MyModel(BaseModel):
foo: MyEnum
# Works
json_data = '{"foo": "value"}'
print(MyModel.model_validate_json(json_data))
# Validation error
json_data = '{"foo": "KEY"}'
print(MyModel.model_validate_json(json_data))
Converting to a typing Literal is not an option in my case because the enum is already used many other places in the codebase.
Sorry just realized I had a typo in my original message which probably confused things. Fixed now.
I see now, yes pydantic uses the value for the actual content, but so does argdantic to be fair. Here's how it works:
In practical terms, using your example:
from enum import Enum
from argdantic import ArgParser
from pydantic import BaseModel
class MyEnum(Enum):
key1 = "value1"
key2 = "value2"
class MyModel(BaseModel):
foo: MyEnum
cli = ArgParser()
@cli.command()
def main(cfg: MyModel):
print(type(cfg.foo))
print(cfg.foo)
print(cfg.foo.name)
print(cfg.foo.value)
In this case the help command will provide you: [foo [key1|key2]](usage: cli.py [-h] --cfg.foo [key1|key2])
, but if you provide cli.py --cfg.foo key1
the actual content printed on the parsed model will be:
<enum 'MyEnum'>
MyEnum.key1
key1
value1
The switch is just done internally by the CLI, because it just makes more sense to use the name
field of enums as an actual name :) but the returned value, once parsed, is the enum object, which contains the value.
I still don't get what you need to accomplish, so apologies if this is not what you wanted!
I'd be down to submit a PR for this if you're open to it. Pointers on how you'd like the interface to be defined would be helpful though.
Is your feature request related to a problem? Please describe. I'm working on a tool which autogenerates github actions from python scripts. Argdantic uses the enum name to define the allowed values. The problem is that this is inconsistent with pydantic, which uses the enum ~key~ value. This means that pydantic's schema cannot be used to determine the allowed values for an argument.
Describe the solution you'd like Add a configuration option to the arg parser which toggles whether the enum key or value is used.
Describe alternatives you've considered Personally I think the enum value would be a better default in general because the enum key is less flexible. E.g the key cannot contain certain characters. But figure this probably isn't worth a breaking change