From 5a1420e88533cfcb84b6408827aa0d57af78777f Mon Sep 17 00:00:00 2001 From: Vincent Tran <54215135+Shindora@users.noreply.github.com> Date: Thu, 24 Apr 2025 15:49:16 +0700 Subject: [PATCH 01/12] fix: case_sensitive not working for InitSettingsSource --- pydantic_settings/sources/base.py | 43 +++++++++++++++++++++++-------- tests/test_settings.py | 2 +- 2 files changed, 33 insertions(+), 12 deletions(-) diff --git a/pydantic_settings/sources/base.py b/pydantic_settings/sources/base.py index 71ccaba..82037da 100644 --- a/pydantic_settings/sources/base.py +++ b/pydantic_settings/sources/base.py @@ -258,19 +258,37 @@ def __init__( settings_cls: type[BaseSettings], init_kwargs: dict[str, Any], nested_model_default_partial_update: bool | None = None, + case_sensitive: bool | None = None, ): + super().__init__(settings_cls) + + self.case_sensitive = case_sensitive if case_sensitive is not None else self.config.get('case_sensitive', False) + self.init_kwargs = {} - init_kwarg_names = set(init_kwargs.keys()) + init_kwargs_processed = set() + + init_kwargs_lookup: dict[str, str] + if not self.case_sensitive: + init_kwargs_lookup = {k.lower(): k for k in init_kwargs} + else: + init_kwargs_lookup = {k: k for k in init_kwargs} + for field_name, field_info in settings_cls.model_fields.items(): - alias_names, *_ = _get_alias_names(field_name, field_info) - init_kwarg_name = init_kwarg_names & set(alias_names) - if init_kwarg_name: - preferred_alias = alias_names[0] - init_kwarg_names -= init_kwarg_name - self.init_kwargs[preferred_alias] = init_kwargs[init_kwarg_name.pop()] - self.init_kwargs.update({key: val for key, val in init_kwargs.items() if key in init_kwarg_names}) + canonical_aliases, _ = _get_alias_names(field_name, field_info, case_sensitive=True) + preferred_alias = canonical_aliases[0] + + match_aliases, _ = _get_alias_names(field_name, field_info, case_sensitive=self.case_sensitive) + for alias in match_aliases: + original_kwarg_key = init_kwargs_lookup.get(alias) + if original_kwarg_key is not None and original_kwarg_key not in init_kwargs_processed: + self.init_kwargs[preferred_alias] = init_kwargs[original_kwarg_key] + init_kwargs_processed.add(original_kwarg_key) + break + + for original_key, value in init_kwargs.items(): + if original_key not in init_kwargs_processed: + self.init_kwargs[original_key] = value - super().__init__(settings_cls) self.nested_model_default_partial_update = ( nested_model_default_partial_update if nested_model_default_partial_update is not None @@ -278,7 +296,6 @@ def __init__( ) def get_field_value(self, field: FieldInfo, field_name: str) -> tuple[Any, str, bool]: - # Nothing to do here. Only implement the return statement to make mypy happy return None, '', False def __call__(self) -> dict[str, Any]: @@ -289,7 +306,11 @@ def __call__(self) -> dict[str, Any]: ) def __repr__(self) -> str: - return f'{self.__class__.__name__}(init_kwargs={self.init_kwargs!r})' + return ( + f'{self.__class__.__name__}(init_kwargs={self.init_kwargs!r}, ' + f'case_sensitive={self.case_sensitive!r}, ' + f'nested_model_default_partial_update={self.nested_model_default_partial_update!r})' + ) class PydanticBaseEnvSettingsSource(PydanticBaseSettingsSource): diff --git a/tests/test_settings.py b/tests/test_settings.py index a7bd86c..bc6fab3 100644 --- a/tests/test_settings.py +++ b/tests/test_settings.py @@ -860,7 +860,7 @@ def test_case_sensitive(monkeypatch): class Settings(BaseSettings): foo: str - model_config = SettingsConfigDict(case_sensitive=True) + model_config = SettingsConfigDict(case_sensitive=True, extra='allow') # Need to patch os.environ to get build to work on Windows, where os.environ is case insensitive monkeypatch.setattr(os, 'environ', value={'Foo': 'foo'}) From c769e930041a9de17d5bf7e33c1cbccf88380329 Mon Sep 17 00:00:00 2001 From: Vincent Tran <54215135+Shindora@users.noreply.github.com> Date: Thu, 24 Apr 2025 16:19:02 +0700 Subject: [PATCH 02/12] Fix: Update test_settings.py --- tests/test_settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_settings.py b/tests/test_settings.py index bc6fab3..a7bd86c 100644 --- a/tests/test_settings.py +++ b/tests/test_settings.py @@ -860,7 +860,7 @@ def test_case_sensitive(monkeypatch): class Settings(BaseSettings): foo: str - model_config = SettingsConfigDict(case_sensitive=True, extra='allow') + model_config = SettingsConfigDict(case_sensitive=True) # Need to patch os.environ to get build to work on Windows, where os.environ is case insensitive monkeypatch.setattr(os, 'environ', value={'Foo': 'foo'}) From 6f02ba0f44ee0180a68142a74a97a252cbf5a9c7 Mon Sep 17 00:00:00 2001 From: Vincent Tran <54215135+Shindora@users.noreply.github.com> Date: Thu, 24 Apr 2025 16:31:04 +0700 Subject: [PATCH 03/12] Update base.py --- pydantic_settings/sources/base.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/pydantic_settings/sources/base.py b/pydantic_settings/sources/base.py index 82037da..e5e6c47 100644 --- a/pydantic_settings/sources/base.py +++ b/pydantic_settings/sources/base.py @@ -306,11 +306,7 @@ def __call__(self) -> dict[str, Any]: ) def __repr__(self) -> str: - return ( - f'{self.__class__.__name__}(init_kwargs={self.init_kwargs!r}, ' - f'case_sensitive={self.case_sensitive!r}, ' - f'nested_model_default_partial_update={self.nested_model_default_partial_update!r})' - ) + return f'{self.__class__.__name__}(init_kwargs={self.init_kwargs!r})' class PydanticBaseEnvSettingsSource(PydanticBaseSettingsSource): From d42cf920b228313cc61ddb8088c81174bb24956e Mon Sep 17 00:00:00 2001 From: Vincent Tran <54215135+Shindora@users.noreply.github.com> Date: Thu, 24 Apr 2025 17:15:54 +0700 Subject: [PATCH 04/12] fix: add unittest for case-insensitive alias matching in InitSettingsSource --- tests/test_settings.py | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/tests/test_settings.py b/tests/test_settings.py index a7bd86c..28b2dac 100644 --- a/tests/test_settings.py +++ b/tests/test_settings.py @@ -627,6 +627,45 @@ class SettingsDefaultsA(BaseSettings, env_nested_delimiter='__', nested_model_de } +def test_env_source_case_sensitive(monkeypatch): + """Tests EnvSettingsSource with case_sensitive=True.""" + + class Settings(BaseSettings): + foo: str + model_config = SettingsConfigDict(case_sensitive=True) + + monkeypatch.setenv('Foo', 'foo_env_value') + with pytest.raises(ValidationError) as exc_info: + Settings() + assert exc_info.value.errors(include_url=False) == [ + {'type': 'missing', 'loc': ('foo',), 'msg': 'Field required', 'input': {}} + ] + monkeypatch.delenv('Foo', raising=False) + + monkeypatch.setenv('foo', 'foo_env_value') + s = Settings() + assert s.foo == 'foo_env_value' + monkeypatch.delenv('foo', raising=False) + + +def test_env_source_case_insensitive(monkeypatch): + """Tests EnvSettingsSource with case_sensitive=False.""" + + class Settings(BaseSettings): + foo: str + model_config = SettingsConfigDict(case_sensitive=False) + + monkeypatch.setenv('Foo', 'foo_env_value') + s_upper = Settings() + assert s_upper.foo == 'foo_env_value' + monkeypatch.delenv('Foo', raising=False) + + monkeypatch.setenv('foo', 'foo_env_value_lower') + s_lower = Settings() + assert s_lower.foo == 'foo_env_value_lower' + monkeypatch.delenv('foo', raising=False) + + def test_init_kwargs_nested_model_default_partial_update(env): class DeepSubModel(BaseModel): v4: str @@ -860,7 +899,7 @@ def test_case_sensitive(monkeypatch): class Settings(BaseSettings): foo: str - model_config = SettingsConfigDict(case_sensitive=True) + model_config = SettingsConfigDict(case_sensitive=True, extra='allow') # Need to patch os.environ to get build to work on Windows, where os.environ is case insensitive monkeypatch.setattr(os, 'environ', value={'Foo': 'foo'}) From dad51feebf1ccbd75a89f1334990cb7e28cbc6f8 Mon Sep 17 00:00:00 2001 From: Vincent Tran <54215135+Shindora@users.noreply.github.com> Date: Thu, 24 Apr 2025 17:25:32 +0700 Subject: [PATCH 05/12] unittest: case-insensitive alias matching in InitSettingsSource --- tests/test_settings.py | 68 ++++++++++++------------------------------ 1 file changed, 19 insertions(+), 49 deletions(-) diff --git a/tests/test_settings.py b/tests/test_settings.py index 28b2dac..d631b87 100644 --- a/tests/test_settings.py +++ b/tests/test_settings.py @@ -627,45 +627,6 @@ class SettingsDefaultsA(BaseSettings, env_nested_delimiter='__', nested_model_de } -def test_env_source_case_sensitive(monkeypatch): - """Tests EnvSettingsSource with case_sensitive=True.""" - - class Settings(BaseSettings): - foo: str - model_config = SettingsConfigDict(case_sensitive=True) - - monkeypatch.setenv('Foo', 'foo_env_value') - with pytest.raises(ValidationError) as exc_info: - Settings() - assert exc_info.value.errors(include_url=False) == [ - {'type': 'missing', 'loc': ('foo',), 'msg': 'Field required', 'input': {}} - ] - monkeypatch.delenv('Foo', raising=False) - - monkeypatch.setenv('foo', 'foo_env_value') - s = Settings() - assert s.foo == 'foo_env_value' - monkeypatch.delenv('foo', raising=False) - - -def test_env_source_case_insensitive(monkeypatch): - """Tests EnvSettingsSource with case_sensitive=False.""" - - class Settings(BaseSettings): - foo: str - model_config = SettingsConfigDict(case_sensitive=False) - - monkeypatch.setenv('Foo', 'foo_env_value') - s_upper = Settings() - assert s_upper.foo == 'foo_env_value' - monkeypatch.delenv('Foo', raising=False) - - monkeypatch.setenv('foo', 'foo_env_value_lower') - s_lower = Settings() - assert s_lower.foo == 'foo_env_value_lower' - monkeypatch.delenv('foo', raising=False) - - def test_init_kwargs_nested_model_default_partial_update(env): class DeepSubModel(BaseModel): v4: str @@ -896,18 +857,27 @@ class Settings(BaseSettings): def test_case_sensitive(monkeypatch): - class Settings(BaseSettings): - foo: str + class CaseSensitiveSettings(BaseSettings): + foo: str - model_config = SettingsConfigDict(case_sensitive=True, extra='allow') + model_config = SettingsConfigDict(case_sensitive=True, extra='allow') - # Need to patch os.environ to get build to work on Windows, where os.environ is case insensitive - monkeypatch.setattr(os, 'environ', value={'Foo': 'foo'}) - with pytest.raises(ValidationError) as exc_info: - Settings() - assert exc_info.value.errors(include_url=False) == [ - {'type': 'missing', 'loc': ('foo',), 'msg': 'Field required', 'input': {}} - ] + # Test when case sensitivity is enabled + monkeypatch.setattr(os, 'environ', value={'Foo': 'foo_value'}) + with pytest.raises(ValidationError) as exc_info: + CaseSensitiveSettings() + assert exc_info.value.errors(include_url=False) == [ + {'type': 'missing', 'loc': ('foo',), 'msg': 'Field required', 'input': {}} + ] + + class CaseInsensitiveSettings(BaseSettings): + foo: str + + model_config = SettingsConfigDict(case_sensitive=False, extra='allow') + + monkeypatch.setattr(os, 'environ', value={'Foo': 'foo_value'}) + settings = CaseInsensitiveSettings() + assert settings.foo == 'foo_value' @pytest.mark.parametrize('env_nested_delimiter', [None, '']) From 1bd8b15e1225ad2d9f40d7fe54c878e43f13ed71 Mon Sep 17 00:00:00 2001 From: Vincent Tran <54215135+Shindora@users.noreply.github.com> Date: Thu, 24 Apr 2025 17:28:31 +0700 Subject: [PATCH 06/12] unittest: case-insensitive alias matching in InitSettingsSource --- tests/test_settings.py | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/tests/test_settings.py b/tests/test_settings.py index d631b87..a2c4dfc 100644 --- a/tests/test_settings.py +++ b/tests/test_settings.py @@ -858,26 +858,26 @@ class Settings(BaseSettings): def test_case_sensitive(monkeypatch): class CaseSensitiveSettings(BaseSettings): - foo: str + foo: str - model_config = SettingsConfigDict(case_sensitive=True, extra='allow') + model_config = SettingsConfigDict(case_sensitive=True, extra='allow') - # Test when case sensitivity is enabled - monkeypatch.setattr(os, 'environ', value={'Foo': 'foo_value'}) - with pytest.raises(ValidationError) as exc_info: - CaseSensitiveSettings() - assert exc_info.value.errors(include_url=False) == [ - {'type': 'missing', 'loc': ('foo',), 'msg': 'Field required', 'input': {}} - ] + # Test when case sensitivity is enabled + monkeypatch.setattr(os, 'environ', value={'Foo': 'foo_value'}) + with pytest.raises(ValidationError) as exc_info: + CaseSensitiveSettings() + assert exc_info.value.errors(include_url=False) == [ + {'type': 'missing', 'loc': ('foo',), 'msg': 'Field required', 'input': {}} + ] class CaseInsensitiveSettings(BaseSettings): - foo: str + foo: str - model_config = SettingsConfigDict(case_sensitive=False, extra='allow') + model_config = SettingsConfigDict(case_sensitive=False, extra='allow') - monkeypatch.setattr(os, 'environ', value={'Foo': 'foo_value'}) - settings = CaseInsensitiveSettings() - assert settings.foo == 'foo_value' + monkeypatch.setattr(os, 'environ', value={'Foo': 'foo_value'}) + settings = CaseInsensitiveSettings() + assert settings.foo == 'foo_value' @pytest.mark.parametrize('env_nested_delimiter', [None, '']) From 3bd506a06a90af426e24bd095a7212cf4f6a2fbf Mon Sep 17 00:00:00 2001 From: Vincent Tran <54215135+Shindora@users.noreply.github.com> Date: Thu, 24 Apr 2025 17:56:53 +0700 Subject: [PATCH 07/12] unittest: test init_kwargs.items() --- tests/test_settings.py | 43 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/tests/test_settings.py b/tests/test_settings.py index a2c4dfc..f587906 100644 --- a/tests/test_settings.py +++ b/tests/test_settings.py @@ -879,6 +879,49 @@ class CaseInsensitiveSettings(BaseSettings): settings = CaseInsensitiveSettings() assert settings.foo == 'foo_value' +def test_init_settings_source_extra_fields_case_sensitive(monkeypatch): + class CaseSensitiveSettings(BaseSettings): + foo: str = Field(..., alias='FOO') + + model_config = SettingsConfigDict(case_sensitive=True, extra='allow') + + monkeypatch.setattr(os, 'environ', value={}) + init_kwargs_case_sensitive = { + 'FOO': 'foo_value', + 'extra_field': 'extra_value', + 'Foo': 'wrong_value' + } + with pytest.raises(ValidationError) as exc_info: + CaseSensitiveSettings(**init_kwargs_case_sensitive) + assert exc_info.value.errors(include_url=False) == [ + {'type': 'missing', 'loc': ('foo',), 'msg': 'Field required', 'input': init_kwargs_case_sensitive} + ] + + # Test with correct case and extra field + monkeypatch.setattr(os, 'environ', value={}) + settings_correct = CaseSensitiveSettings(FOO='foo_value', extra_field='extra_value') + assert settings_correct.foo == 'foo_value' + assert settings_correct.__pydantic_extra__ == {'extra_field': 'extra_value'} + + class CaseInsensitiveSettings(BaseSettings): + foo: str = Field(..., alias='FOO') + + model_config = SettingsConfigDict(case_sensitive=False, extra='allow') + + # Test when case sensitivity is disabled + monkeypatch.setattr(os, 'environ', value={}) + init_kwargs_case_insensitive = { + 'Foo': 'foo_value', + 'extra_field': 'extra_value', + 'EXTRA_FIELD': 'another_value' + } + settings = CaseInsensitiveSettings(**init_kwargs_case_insensitive) + assert settings.foo == 'foo_value' + assert settings.__pydantic_extra__ == { + 'extra_field': 'extra_value', + 'EXTRA_FIELD': 'another_value' + } + @pytest.mark.parametrize('env_nested_delimiter', [None, '']) def test_case_sensitive_no_nested_delimiter(monkeypatch, env_nested_delimiter): From 054c0b71d7991f5c8d92c504eaef62ee59f00ffc Mon Sep 17 00:00:00 2001 From: Vincent Tran <54215135+Shindora@users.noreply.github.com> Date: Thu, 24 Apr 2025 18:04:41 +0700 Subject: [PATCH 08/12] unittest: test init_kwargs.items() --- tests/test_settings.py | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/tests/test_settings.py b/tests/test_settings.py index f587906..6197575 100644 --- a/tests/test_settings.py +++ b/tests/test_settings.py @@ -885,11 +885,11 @@ class CaseSensitiveSettings(BaseSettings): model_config = SettingsConfigDict(case_sensitive=True, extra='allow') - monkeypatch.setattr(os, 'environ', value={}) + # Test when case sensitivity is enabled (missing correct alias) + monkeypatch.setattr(os, 'environ', value={}) # Empty env to isolate init_kwargs init_kwargs_case_sensitive = { - 'FOO': 'foo_value', + 'Foo': 'wrong_value', # Wrong case for alias 'FOO' 'extra_field': 'extra_value', - 'Foo': 'wrong_value' } with pytest.raises(ValidationError) as exc_info: CaseSensitiveSettings(**init_kwargs_case_sensitive) @@ -898,8 +898,9 @@ class CaseSensitiveSettings(BaseSettings): ] # Test with correct case and extra field - monkeypatch.setattr(os, 'environ', value={}) - settings_correct = CaseSensitiveSettings(FOO='foo_value', extra_field='extra_value') + monkeypatch.setattr(os, 'environ', value={}) # Ensure no env interference + init_kwargs_correct_case = {'FOO': 'foo_value', 'extra_field': 'extra_value'} + settings_correct = CaseSensitiveSettings(**init_kwargs_correct_case) assert settings_correct.foo == 'foo_value' assert settings_correct.__pydantic_extra__ == {'extra_field': 'extra_value'} @@ -909,18 +910,15 @@ class CaseInsensitiveSettings(BaseSettings): model_config = SettingsConfigDict(case_sensitive=False, extra='allow') # Test when case sensitivity is disabled - monkeypatch.setattr(os, 'environ', value={}) + monkeypatch.setattr(os, 'environ', value={}) # Empty env to isolate init_kwargs init_kwargs_case_insensitive = { - 'Foo': 'foo_value', + 'Foo': 'foo_value', # Matches alias 'FOO' case-insensitively 'extra_field': 'extra_value', - 'EXTRA_FIELD': 'another_value' + 'EXTRA_FIELD': 'another_value', } settings = CaseInsensitiveSettings(**init_kwargs_case_insensitive) assert settings.foo == 'foo_value' - assert settings.__pydantic_extra__ == { - 'extra_field': 'extra_value', - 'EXTRA_FIELD': 'another_value' - } + assert settings.__pydantic_extra__ == {'extra_field': 'extra_value', 'EXTRA_FIELD': 'another_value'} @pytest.mark.parametrize('env_nested_delimiter', [None, '']) From 8eba6e0d521d1228732910f5cc9047720760a3b6 Mon Sep 17 00:00:00 2001 From: Vincent Tran <54215135+Shindora@users.noreply.github.com> Date: Thu, 24 Apr 2025 18:07:54 +0700 Subject: [PATCH 09/12] unittest: test init_kwargs.items() --- tests/test_settings.py | 58 ++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 31 deletions(-) diff --git a/tests/test_settings.py b/tests/test_settings.py index 6197575..3abd3a2 100644 --- a/tests/test_settings.py +++ b/tests/test_settings.py @@ -881,44 +881,40 @@ class CaseInsensitiveSettings(BaseSettings): def test_init_settings_source_extra_fields_case_sensitive(monkeypatch): class CaseSensitiveSettings(BaseSettings): - foo: str = Field(..., alias='FOO') + foo: str = Field(..., alias="FOO") + model_config = SettingsConfigDict(case_sensitive=True, extra="allow") - model_config = SettingsConfigDict(case_sensitive=True, extra='allow') - - # Test when case sensitivity is enabled (missing correct alias) - monkeypatch.setattr(os, 'environ', value={}) # Empty env to isolate init_kwargs - init_kwargs_case_sensitive = { - 'Foo': 'wrong_value', # Wrong case for alias 'FOO' - 'extra_field': 'extra_value', - } + # Test case-sensitive with missing alias + monkeypatch.setattr(os, "environ", value={}) + init_kwargs = {"Foo": "wrong_value", "extra_field": "extra_value"} with pytest.raises(ValidationError) as exc_info: - CaseSensitiveSettings(**init_kwargs_case_sensitive) + CaseSensitiveSettings(**init_kwargs) assert exc_info.value.errors(include_url=False) == [ - {'type': 'missing', 'loc': ('foo',), 'msg': 'Field required', 'input': init_kwargs_case_sensitive} + { + "type": "missing", + "loc": ("FOO",), + "msg": "Field required", + "input": init_kwargs, + } ] - # Test with correct case and extra field - monkeypatch.setattr(os, 'environ', value={}) # Ensure no env interference - init_kwargs_correct_case = {'FOO': 'foo_value', 'extra_field': 'extra_value'} - settings_correct = CaseSensitiveSettings(**init_kwargs_correct_case) - assert settings_correct.foo == 'foo_value' - assert settings_correct.__pydantic_extra__ == {'extra_field': 'extra_value'} + # Test case-sensitive with correct alias and extra field + monkeypatch.setattr(os, "environ", value={}) + init_kwargs = {"FOO": "foo_value", "extra_field": "extra_value"} + settings = CaseSensitiveSettings(**init_kwargs) + assert settings.foo == "foo_value" + assert settings.__pydantic_extra__ == {"extra_field": "extra_value"} class CaseInsensitiveSettings(BaseSettings): - foo: str = Field(..., alias='FOO') - - model_config = SettingsConfigDict(case_sensitive=False, extra='allow') - - # Test when case sensitivity is disabled - monkeypatch.setattr(os, 'environ', value={}) # Empty env to isolate init_kwargs - init_kwargs_case_insensitive = { - 'Foo': 'foo_value', # Matches alias 'FOO' case-insensitively - 'extra_field': 'extra_value', - 'EXTRA_FIELD': 'another_value', - } - settings = CaseInsensitiveSettings(**init_kwargs_case_insensitive) - assert settings.foo == 'foo_value' - assert settings.__pydantic_extra__ == {'extra_field': 'extra_value', 'EXTRA_FIELD': 'another_value'} + foo: str = Field(..., alias="FOO") + model_config = SettingsConfigDict(case_sensitive=False, extra="allow") + + # Test case-insensitive with extra field + monkeypatch.setattr(os, "environ", value={}) + init_kwargs = {"Foo": "foo_value", "extra_field": "extra_value"} + settings = CaseInsensitiveSettings(**init_kwargs) + assert settings.foo == "foo_value" + assert settings.__pydantic_extra__ == {"extra_field": "extra_value"} @pytest.mark.parametrize('env_nested_delimiter', [None, '']) From 2e2a99f719e510434523f83881abd6c29bfbf2ec Mon Sep 17 00:00:00 2001 From: Vincent Tran <54215135+Shindora@users.noreply.github.com> Date: Thu, 24 Apr 2025 18:10:32 +0700 Subject: [PATCH 10/12] chore: replace double quotes by single quote --- tests/test_settings.py | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/tests/test_settings.py b/tests/test_settings.py index 3abd3a2..5d7d3db 100644 --- a/tests/test_settings.py +++ b/tests/test_settings.py @@ -881,40 +881,40 @@ class CaseInsensitiveSettings(BaseSettings): def test_init_settings_source_extra_fields_case_sensitive(monkeypatch): class CaseSensitiveSettings(BaseSettings): - foo: str = Field(..., alias="FOO") - model_config = SettingsConfigDict(case_sensitive=True, extra="allow") + foo: str = Field(..., alias='FOO') + model_config = SettingsConfigDict(case_sensitive=True, extra='allow') # Test case-sensitive with missing alias - monkeypatch.setattr(os, "environ", value={}) - init_kwargs = {"Foo": "wrong_value", "extra_field": "extra_value"} + monkeypatch.setattr(os, 'environ', value={}) + init_kwargs = {'Foo': 'wrong_value', 'extra_field': 'extra_value'} with pytest.raises(ValidationError) as exc_info: CaseSensitiveSettings(**init_kwargs) assert exc_info.value.errors(include_url=False) == [ { - "type": "missing", - "loc": ("FOO",), - "msg": "Field required", - "input": init_kwargs, + 'type': 'missing', + 'loc': ('FOO',), + 'msg': 'Field required', + 'input': init_kwargs, } ] # Test case-sensitive with correct alias and extra field - monkeypatch.setattr(os, "environ", value={}) - init_kwargs = {"FOO": "foo_value", "extra_field": "extra_value"} + monkeypatch.setattr(os, 'environ', value={}) + init_kwargs = {'FOO': 'foo_value', 'extra_field': 'extra_value'} settings = CaseSensitiveSettings(**init_kwargs) - assert settings.foo == "foo_value" - assert settings.__pydantic_extra__ == {"extra_field": "extra_value"} + assert settings.foo == 'foo_value' + assert settings.__pydantic_extra__ == {'extra_field': 'extra_value'} class CaseInsensitiveSettings(BaseSettings): - foo: str = Field(..., alias="FOO") - model_config = SettingsConfigDict(case_sensitive=False, extra="allow") + foo: str = Field(..., alias='FOO') + model_config = SettingsConfigDict(case_sensitive=False, extra='allow') # Test case-insensitive with extra field - monkeypatch.setattr(os, "environ", value={}) - init_kwargs = {"Foo": "foo_value", "extra_field": "extra_value"} + monkeypatch.setattr(os, 'environ', value={}) + init_kwargs = {'Foo': 'foo_value', 'extra_field': 'extra_value'} settings = CaseInsensitiveSettings(**init_kwargs) - assert settings.foo == "foo_value" - assert settings.__pydantic_extra__ == {"extra_field": "extra_value"} + assert settings.foo == 'foo_value' + assert settings.__pydantic_extra__ == {'extra_field': 'extra_value'} @pytest.mark.parametrize('env_nested_delimiter', [None, '']) From 4d1b0b7a2bbb216b3f854153fe031af367ebc7f0 Mon Sep 17 00:00:00 2001 From: vi tran Date: Fri, 25 Apr 2025 10:00:12 +0700 Subject: [PATCH 11/12] refactor: lint format --- tests/test_settings.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_settings.py b/tests/test_settings.py index 5d7d3db..1533f5f 100644 --- a/tests/test_settings.py +++ b/tests/test_settings.py @@ -879,6 +879,7 @@ class CaseInsensitiveSettings(BaseSettings): settings = CaseInsensitiveSettings() assert settings.foo == 'foo_value' + def test_init_settings_source_extra_fields_case_sensitive(monkeypatch): class CaseSensitiveSettings(BaseSettings): foo: str = Field(..., alias='FOO') From bc2c679d9f01f8d9def5594a3b26d7354bf23259 Mon Sep 17 00:00:00 2001 From: vi tran Date: Fri, 25 Apr 2025 10:04:45 +0700 Subject: [PATCH 12/12] revert: test_case_sensitive --- tests/test_settings.py | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/tests/test_settings.py b/tests/test_settings.py index 1533f5f..bb3297c 100644 --- a/tests/test_settings.py +++ b/tests/test_settings.py @@ -857,28 +857,19 @@ class Settings(BaseSettings): def test_case_sensitive(monkeypatch): - class CaseSensitiveSettings(BaseSettings): + class Settings(BaseSettings): foo: str - model_config = SettingsConfigDict(case_sensitive=True, extra='allow') + model_config = SettingsConfigDict(case_sensitive=True) - # Test when case sensitivity is enabled - monkeypatch.setattr(os, 'environ', value={'Foo': 'foo_value'}) + # Need to patch os.environ to get build to work on Windows, where os.environ is case insensitive + monkeypatch.setattr(os, 'environ', value={'Foo': 'foo'}) with pytest.raises(ValidationError) as exc_info: - CaseSensitiveSettings() + Settings() assert exc_info.value.errors(include_url=False) == [ {'type': 'missing', 'loc': ('foo',), 'msg': 'Field required', 'input': {}} ] - class CaseInsensitiveSettings(BaseSettings): - foo: str - - model_config = SettingsConfigDict(case_sensitive=False, extra='allow') - - monkeypatch.setattr(os, 'environ', value={'Foo': 'foo_value'}) - settings = CaseInsensitiveSettings() - assert settings.foo == 'foo_value' - def test_init_settings_source_extra_fields_case_sensitive(monkeypatch): class CaseSensitiveSettings(BaseSettings):