CLI use of `IntEnum` not working with nested models
lsg551 opened this issue · comments
Description
The pydantic docs about the usage of enums in CLIs state that enum.IntEnum can perfectly be used with CLIs, where the enum's field names are eventually accepted as flag values.
[excerpt] from the docs:
CLI argument parsing of literals and enums are converted into CLI choices.
import sys
from enum import IntEnum
from pydantic_settings import BaseSettings
class Fruit(IntEnum):
pear = 0
kiwi = 1
lime = 2
class Settings(BaseSettings, cli_parse_args=True):
fruit: Fruit
sys.argv = ['example.py', '--fruit', 'lime']
print(Settings().model_dump())
#> {'fruit': <Fruit.lime: 2>}And this works totally fine. But as soon as a model is nested, it raises a validation error. For example, consider this scenario:
from enum import IntEnum
class LogLevel(IntEnum):
CRITICAL = 50
ERROR = 40
WARNING = 30
INFO = 20
DEBUG = 10
@pydantic.dataclasses.dataclass
class LoggingOptions:
level: LogLevel = LogLevel.INFO
class Settings(BaseSettings):
model_config = SettingsConfigDict(
cli_parse_args=True,
cli_kebab_case=True,
cli_use_class_docs_for_groups=True,
cli_avoid_json=True,
frozen=True,
)
level: LogLevel = LogLevel.INFO # this works
logging: LoggingOptions # this DOES NOT workWhen tested, the root level flags work as intended with integer enums:
sys.argv = ['example.py', '--level', 'DEBUG']
settings = Settings()However, nested ones do not:
sys.argv = ['example.py', '--logging.level', 'DEBUG']
settings = Settings()and this will raise:
Traceback (most recent call last):
File "/project/sandbox/main.py", line 55, in <module>
settings = Settings()
^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/pydantic_settings/main.py", line 176, in __init__
super().__init__(
File "/usr/local/lib/python3.12/site-packages/pydantic/main.py", line 253, in __init__
validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
pydantic_core._pydantic_core.ValidationError: 1 validation error for Settings
logging.level
Input should be 50, 50, 40, 30, 30, 20, 10 or 0 [type=enum, input_value='DEBUG', input_type=str]
For further information visit https://errors.pydantic.dev/2.11/v/enumExpected Behaviour
I expected this to work properly with nested models too, just like root level objects. However, I am not familiar enough with pydantic or pydantic-settings to tell whether this is intended / expected behaviour.
I searched the docs and issues, but couldn't find related information. Sorry, if this was already brought up.
How to replicate
Note that the code of the above examples is simplified, but I created a codesandbox to replicate this: https://codesandbox.io/p/devbox/59rv9y?embed=1&file=%2Fmain.py
Affected Versions
I tested with the latest versions of pydantic and pydantic-settings:
pydantic == 2.11.3pydantic-settings == 2.8.1
and used Python 3.12 as well as 3.13.
@kschwab please take a look when you have time. sorry for pinging you too much, you are the only person who is expert in CLI.
No worries @hramezani, happy to help. Opened #589 for resolution.
Thanks @kschwab for the fix PR and sorry for asking you to fix a non cli bug.
Greatly appreciate that, thanks!