pydantic / pydantic-settings

Settings management using pydantic
https://docs.pydantic.dev/latest/usage/pydantic_settings/
MIT License
508 stars 50 forks source link

`BaseSettings` initialisation causes nested `BaseModel.model_fields_set` to be incorrect #263

Closed MickVermeulen closed 3 months ago

MickVermeulen commented 3 months ago

Due to a change in 2784a7013d0bccb5c76c2db78befe0c266baac55 to dump_python any of the init kwargs, any nested structure of models is dumped to a dictionary, including default fields. This dictionary is then later used to instantiate the BaseSettings model itself, which causes all fields on child models to be set.

Take for example the following minimum example:

from pydantic import BaseModel
from pydantic_settings import BaseSettings

if __name__ == "__main__":
    class Child(BaseModel):
        foo: str = "bar"

    class Parent(BaseSettings):
        child: Child

    parent = Parent(child=Child())

    assert not parent.child.model_fields_set

Even though the foo property on Child is never explicitly set, it will show up under model_fields_set.

Would there be some way to retrieve the original behaviour? I actually rely on this to be able to merge models myself. Overriding defaults becomes difficult when model_fields_set is not correct as you can no longer keep a default value apart from a user-defined value that happens to overlap with a default value.

hramezani commented 3 months ago

Thanks @MickVermeulen for reporting this. but we reverted this change on https://github.com/pydantic/pydantic-settings/commit/b3a67e92d6d4f58d35c47732fec34d7cda9d7df2 and it is available in pydantic-settings 2.2.1