Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

partial specify the sub model value does not work #363

Closed
braindevices opened this issue Aug 8, 2024 · 3 comments · Fixed by #348
Closed

partial specify the sub model value does not work #363

braindevices opened this issue Aug 8, 2024 · 3 comments · Fixed by #348
Assignees

Comments

@braindevices
Copy link

class SubModel(BaseModel):
    v1: str = "default"
    v2: bytes = b"hello"
    v3: int = 3

class Settings(BaseSettings):
    model_config = SettingsConfigDict(
        cli_prog_name="prog1",
        cli_parse_args=True
    )

    v0: str = "ok"
    sub_model: SubModel = SubModel(v1="top default", v3=33)

sys.argv = [
    'example.py',
    "--sub_model.v1='cli'"
]
print(Settings())
# > v0='from env' sub_model=SubModel(v1="'cli'", v2=b'hello', v3=3)

expected value:

# > v0='from env' sub_model=SubModel(v1="'cli'", v2=b'hello', v3=33)

similar cause of the problem: if v3 does not have default in SubModel, it raise an error:

pydantic_core._pydantic_core.ValidationError: 1 validation error for Settings
sub_model.v3
  Field required [type=missing, input_value={'v1': "'cli'"}, input_type=dict]

I think we need to enable partial update with nested sub model, otherwise, the BaseSettings does not really support nested model field as cli arg or environment variable. If we decide not to support partial update, I guess it is better to drop the env_nested and --field.subfield idea completely. Because this behaviour, especially the silent fallback to SubModel's default will completely surprise the user.

@hramezani
Copy link
Member

Thanks @braindevices for reporting this issue.

I think the behavior is the same as the env settings source. if you run the example code by SUB_MODEL__V1=cli python example.py you will get the same result.

There was a long discussion about this topic at #347. it is a pydantic-settings V2 limitation.

@kschwab
Copy link
Contributor

kschwab commented Aug 21, 2024

Hi @braindevices, I've added a flag nested_model_default_partial_update that enables partial updates for default model objects. Could you help verify it resolves your issue and post a simple test for your use case? I believe the case posted in the description is now resolved:

import os
import sys
from pydantic import BaseModel
from pydantic_settings import BaseSettings, SettingsConfigDict

class SubModel(BaseModel):
    v1: str = "default"
    v2: bytes = b"hello"
    v3: int = 3

class Settings(BaseSettings):
    model_config = SettingsConfigDict(
        nested_model_default_partial_update=True,
        cli_prog_name="prog1",
        cli_parse_args=True,
    )

    v0: str = "ok"
    sub_model: SubModel = SubModel(v1="top default", v3=33)

os.environ["V0"] = "from env"
sys.argv = [
    "example.py",
    "--sub_model.v1='cli'",
]
print(Settings())
#> v0='from env' sub_model=SubModel(v1="'cli'", v2=b'hello', v3=33)

@braindevices
Copy link
Author

thanks, looking forward to see new release

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants