Closed user1584 closed 3 weeks ago
Thanks @user1584 for reporting this issue.
pydantic-settings
considers custom_str: CustomStr
as a complex field and that's why it parses the value by json.loads
.
Right now, it isn't possible to disable the json parsing. probably we need a flag to disable it.
take a look at the similar issue and my comment on it.
Thanks for the incredibly quick answer! How/where does pydantic-settings decide whether a type is a complex field or simple enough to pass the content of the environment variable directly? Is this something that could be adapted? A flag might also a good option. Could that be set per field?
How/where does pydantic-settings decide whether a type is a complex field or simple enough to pass the content of the environment variable directly? Is this something that could be adapted?
It happens here. probably you can create a custom settings source inherited from EnvSettingsSource and change the behaviour for this field.
A flag might also a good option. Could that be set per field?
Not sure, because the Field
is imported from Pydantic
. agree that is would be good to have control over this behaviour per field
Obviously I am mostly interested to solve my own little problem and I have next to no idea about the inner workings of pydantic/pydantic-settings. With that in mind, would it be viable solution to check whether the RootModels' attribute type is complex?
I monkey-patched the field_is_complex
method like this:
from pydantic.fields import FieldInfo
import pydantic_settings
def patched_field_is_complex(self, field: FieldInfo) -> bool:
"""
Checks whether a field is complex, in which case it will attempt to be parsed as JSON.
Args:
field: The field.
Returns:
Whether the field is complex.
"""
if issubclass(field.annotation, pydantic.RootModel):
return pydantic_settings.sources._annotation_is_complex(field.annotation.__annotations__["root"], field.metadata)
return pydantic_settings.sources._annotation_is_complex(field.annotation, field.metadata)
pydantic_settings.PydanticBaseSettingsSource.field_is_complex=patched_field_is_complex
Of course, this would only be a solution for models that are based on RootModel.
seems good. you can open a PR and change the behavior in pydantic-settings
if you want. you probably need to change _annotation_is_complex and add some test for it.
I created a PR. However, the python 3.8 & 3.9 tests still fail. Do you have an idea why they fail but all other tests work?
I am trying to create an extension of standard str class. My idea was to just create a RootModel based on str and then add some custom logic. However, I encountered strange problems when using the resulting class as part of the settings. My RootModel looks like this (without custom logic):
Initializing with
CustomStr("hello world")
works as expected. The next step was to use it as part of the settings:This results in 'SettingsError: error parsing value for field "custom_str" from source "EnvSettingsSource"' (see complete traceback below). If I switch the type of custom_str from CustomStr to standard str, the example works. During lots of debugging, I noticed that it works if I wrap the string in the environment variable in double quotes like
os.environ["custom_str"] = '"hello world"'
since this can be parsed by json.loads. Note: The order of single and double quotes matters! So, the question is: Is there any way to let pydantic/pydantic_settings handle the custom model like regular str class?I am using pydantic version '2.7.1' and pydantic_settings version '2.2.1'.
Here's the complete traceback: