Skip to content

Commit fa21884

Browse files
authored
Fix nested model field with alias parsing (#400)
1 parent 79090e2 commit fa21884

File tree

2 files changed

+49
-6
lines changed

2 files changed

+49
-6
lines changed

pydantic_settings/sources.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -824,13 +824,14 @@ class Cfg(BaseSettings):
824824
fields = _get_model_fields(annotation)
825825
# `case_sensitive is None` is here to be compatible with the old behavior.
826826
# Has to be removed in V3.
827-
if (case_sensitive is None or case_sensitive) and fields.get(key):
828-
return fields[key]
829-
elif not case_sensitive:
830-
for field_name, f in fields.items():
831-
if field_name.lower() == key.lower():
827+
for field_name, f in fields.items():
828+
if case_sensitive is None or case_sensitive:
829+
if (field_name == key) or (isinstance(f.validation_alias, str) and f.validation_alias == key):
832830
return f
833-
831+
elif (field_name.lower() == key.lower()) or (
832+
isinstance(f.validation_alias, str) and f.validation_alias.lower() == key.lower()
833+
):
834+
return f
834835
return None
835836

836837
def explode_env_vars(self, field_name: str, field: FieldInfo, env_vars: Mapping[str, str | None]) -> dict[str, Any]:

tests/test_settings.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5004,3 +5004,45 @@ class Settings(BaseSettings):
50045004
foo: list[str] = []
50055005

50065006
Settings()
5007+
5008+
5009+
def test_nested_model_field_with_alias(env):
5010+
class NestedSettings(BaseModel):
5011+
foo: List[str] = Field(alias='fooalias')
5012+
5013+
class Settings(BaseSettings):
5014+
model_config = SettingsConfigDict(env_nested_delimiter='__')
5015+
5016+
nested: NestedSettings
5017+
5018+
env.set('nested__fooalias', '["one", "two"]')
5019+
5020+
s = Settings()
5021+
assert s.model_dump() == {'nested': {'foo': ['one', 'two']}}
5022+
5023+
5024+
def test_nested_model_field_with_alias_case_sensitive(monkeypatch):
5025+
class NestedSettings(BaseModel):
5026+
foo: List[str] = Field(alias='fooAlias')
5027+
5028+
class Settings(BaseSettings):
5029+
model_config = SettingsConfigDict(env_nested_delimiter='__', case_sensitive=True)
5030+
5031+
nested: NestedSettings
5032+
5033+
# Need to patch os.environ to get build to work on Windows, where os.environ is case insensitive
5034+
monkeypatch.setattr(os, 'environ', value={'nested__fooalias': '["one", "two"]'})
5035+
with pytest.raises(ValidationError) as exc_info:
5036+
Settings()
5037+
assert exc_info.value.errors(include_url=False) == [
5038+
{
5039+
'type': 'missing',
5040+
'loc': ('nested', 'fooAlias'),
5041+
'msg': 'Field required',
5042+
'input': {'fooalias': '["one", "two"]'},
5043+
}
5044+
]
5045+
5046+
monkeypatch.setattr(os, 'environ', value={'nested__fooAlias': '["one", "two"]'})
5047+
s = Settings()
5048+
assert s.model_dump() == {'nested': {'foo': ['one', 'two']}}

0 commit comments

Comments
 (0)