Skip to content

Commit 5a1420e

Browse files
authored
fix: case_sensitive not working for InitSettingsSource
1 parent 212784c commit 5a1420e

File tree

2 files changed

+33
-12
lines changed

2 files changed

+33
-12
lines changed

pydantic_settings/sources/base.py

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -258,27 +258,44 @@ def __init__(
258258
settings_cls: type[BaseSettings],
259259
init_kwargs: dict[str, Any],
260260
nested_model_default_partial_update: bool | None = None,
261+
case_sensitive: bool | None = None,
261262
):
263+
super().__init__(settings_cls)
264+
265+
self.case_sensitive = case_sensitive if case_sensitive is not None else self.config.get('case_sensitive', False)
266+
262267
self.init_kwargs = {}
263-
init_kwarg_names = set(init_kwargs.keys())
268+
init_kwargs_processed = set()
269+
270+
init_kwargs_lookup: dict[str, str]
271+
if not self.case_sensitive:
272+
init_kwargs_lookup = {k.lower(): k for k in init_kwargs}
273+
else:
274+
init_kwargs_lookup = {k: k for k in init_kwargs}
275+
264276
for field_name, field_info in settings_cls.model_fields.items():
265-
alias_names, *_ = _get_alias_names(field_name, field_info)
266-
init_kwarg_name = init_kwarg_names & set(alias_names)
267-
if init_kwarg_name:
268-
preferred_alias = alias_names[0]
269-
init_kwarg_names -= init_kwarg_name
270-
self.init_kwargs[preferred_alias] = init_kwargs[init_kwarg_name.pop()]
271-
self.init_kwargs.update({key: val for key, val in init_kwargs.items() if key in init_kwarg_names})
277+
canonical_aliases, _ = _get_alias_names(field_name, field_info, case_sensitive=True)
278+
preferred_alias = canonical_aliases[0]
279+
280+
match_aliases, _ = _get_alias_names(field_name, field_info, case_sensitive=self.case_sensitive)
281+
for alias in match_aliases:
282+
original_kwarg_key = init_kwargs_lookup.get(alias)
283+
if original_kwarg_key is not None and original_kwarg_key not in init_kwargs_processed:
284+
self.init_kwargs[preferred_alias] = init_kwargs[original_kwarg_key]
285+
init_kwargs_processed.add(original_kwarg_key)
286+
break
287+
288+
for original_key, value in init_kwargs.items():
289+
if original_key not in init_kwargs_processed:
290+
self.init_kwargs[original_key] = value
272291

273-
super().__init__(settings_cls)
274292
self.nested_model_default_partial_update = (
275293
nested_model_default_partial_update
276294
if nested_model_default_partial_update is not None
277295
else self.config.get('nested_model_default_partial_update', False)
278296
)
279297

280298
def get_field_value(self, field: FieldInfo, field_name: str) -> tuple[Any, str, bool]:
281-
# Nothing to do here. Only implement the return statement to make mypy happy
282299
return None, '', False
283300

284301
def __call__(self) -> dict[str, Any]:
@@ -289,7 +306,11 @@ def __call__(self) -> dict[str, Any]:
289306
)
290307

291308
def __repr__(self) -> str:
292-
return f'{self.__class__.__name__}(init_kwargs={self.init_kwargs!r})'
309+
return (
310+
f'{self.__class__.__name__}(init_kwargs={self.init_kwargs!r}, '
311+
f'case_sensitive={self.case_sensitive!r}, '
312+
f'nested_model_default_partial_update={self.nested_model_default_partial_update!r})'
313+
)
293314

294315

295316
class PydanticBaseEnvSettingsSource(PydanticBaseSettingsSource):

tests/test_settings.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -860,7 +860,7 @@ def test_case_sensitive(monkeypatch):
860860
class Settings(BaseSettings):
861861
foo: str
862862

863-
model_config = SettingsConfigDict(case_sensitive=True)
863+
model_config = SettingsConfigDict(case_sensitive=True, extra='allow')
864864

865865
# Need to patch os.environ to get build to work on Windows, where os.environ is case insensitive
866866
monkeypatch.setattr(os, 'environ', value={'Foo': 'foo'})

0 commit comments

Comments
 (0)