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

2.6.0 breaks sub-modules inheriting from BaseSettings for independent environment variables #449

Closed
rra opened this issue Oct 18, 2024 · 2 comments
Assignees

Comments

@rra
Copy link

rra commented Oct 18, 2024

We are (in a pretty large number of places) intentionally using the pre-2.6 behavior of submodels that inherit from BaseSettings instead of BaseModel as a way to use environment variables to configure those portions of the settings directly without having to use the more complex convention for environment variables that specify the full path down to the field. This allows us to use standardized environment variables for that specific block of settings, regardless of what application settings they're embedded in.

For example, this code works as desired with pydantic-settings 2.5.2, but breaks with 2.6.0:

import os

from pydantic import Field
from pydantic_settings import BaseSettings, SettingsConfigDict


class GitHubConfig(BaseSettings):
    client_id: str
    client_secret: str = Field(validation_alias="GITHUB_CLIENT_SECRET")


class Config(BaseSettings):
    realm: str
    github: GitHubConfig

    model_config = SettingsConfigDict(extra="forbid", env_prefix="APP_")


os.environ["GITHUB_CLIENT_SECRET"] = "some-secret"
os.environ["APP_REALM"] = "example.com"
config = Config.model_validate({"github": {"client_id": "client-id"}})
print(config.model_dump())
# {'realm': 'example.com', 'github': {'client_id': 'client-id', 'client_secret': 'some-secret'}}

With pydantic-settings 2.6.0, it produces the following error:

pydantic_core._pydantic_core.ValidationError: 2 validation errors for Config
realm
  Field required [type=missing, input_value={'github': {'client_id': 'client-id'}}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.9/v/missing
github.GITHUB_CLIENT_SECRET
  Field required [type=missing, input_value={'client_id': 'client-id'}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.9/v/missing

We use this configuration pattern very heavily for Kubernetes applications, since most of the application configuration is injected from the values.yaml file as YAML, but secrets, which have to come from Kubernetes secrets, are then injected via environment variables.

I think this may partially duplicate other issues (specifically #447 and #445), but the descriptions there aren't quite the same and involve more complex functionality that we weren't using, so I thought the separate report may still be useful.

@rra
Copy link
Author

rra commented Oct 18, 2024

I should have added explicitly that this doesn't work in pydantic-settings 2.5.2 if, in the example, GitHubConfig inherits from BaseModel instead. That results in the following error:

github.GITHUB_CLIENT_SECRET
  Field required [type=missing, input_value={'client_id': 'client-id'}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.9/v/missing

@hramezani
Copy link
Member

I reverted the fix that caused the problem and released pydantic-settings 2.6.1.

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

No branches or pull requests

3 participants