Skip to content

Commit

Permalink
Fix nested model field with alias parsing (#400)
Browse files Browse the repository at this point in the history
  • Loading branch information
hramezani authored Sep 12, 2024
1 parent 79090e2 commit fa21884
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 6 deletions.
13 changes: 7 additions & 6 deletions pydantic_settings/sources.py
Original file line number Diff line number Diff line change
Expand Up @@ -824,13 +824,14 @@ class Cfg(BaseSettings):
fields = _get_model_fields(annotation)
# `case_sensitive is None` is here to be compatible with the old behavior.
# Has to be removed in V3.
if (case_sensitive is None or case_sensitive) and fields.get(key):
return fields[key]
elif not case_sensitive:
for field_name, f in fields.items():
if field_name.lower() == key.lower():
for field_name, f in fields.items():
if case_sensitive is None or case_sensitive:
if (field_name == key) or (isinstance(f.validation_alias, str) and f.validation_alias == key):
return f

elif (field_name.lower() == key.lower()) or (
isinstance(f.validation_alias, str) and f.validation_alias.lower() == key.lower()
):
return f
return None

def explode_env_vars(self, field_name: str, field: FieldInfo, env_vars: Mapping[str, str | None]) -> dict[str, Any]:
Expand Down
42 changes: 42 additions & 0 deletions tests/test_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -5004,3 +5004,45 @@ class Settings(BaseSettings):
foo: list[str] = []

Settings()


def test_nested_model_field_with_alias(env):
class NestedSettings(BaseModel):
foo: List[str] = Field(alias='fooalias')

class Settings(BaseSettings):
model_config = SettingsConfigDict(env_nested_delimiter='__')

nested: NestedSettings

env.set('nested__fooalias', '["one", "two"]')

s = Settings()
assert s.model_dump() == {'nested': {'foo': ['one', 'two']}}


def test_nested_model_field_with_alias_case_sensitive(monkeypatch):
class NestedSettings(BaseModel):
foo: List[str] = Field(alias='fooAlias')

class Settings(BaseSettings):
model_config = SettingsConfigDict(env_nested_delimiter='__', case_sensitive=True)

nested: NestedSettings

# Need to patch os.environ to get build to work on Windows, where os.environ is case insensitive
monkeypatch.setattr(os, 'environ', value={'nested__fooalias': '["one", "two"]'})
with pytest.raises(ValidationError) as exc_info:
Settings()
assert exc_info.value.errors(include_url=False) == [
{
'type': 'missing',
'loc': ('nested', 'fooAlias'),
'msg': 'Field required',
'input': {'fooalias': '["one", "two"]'},
}
]

monkeypatch.setattr(os, 'environ', value={'nested__fooAlias': '["one", "two"]'})
s = Settings()
assert s.model_dump() == {'nested': {'foo': ['one', 'two']}}

0 comments on commit fa21884

Please sign in to comment.