Skip to content

Commit 9aec7ae

Browse files
committed
draft
1 parent 1e1d862 commit 9aec7ae

File tree

2 files changed

+55
-5
lines changed

2 files changed

+55
-5
lines changed

packages/settings-library/src/settings_library/base.py

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,12 @@
66
from pydantic import ValidationInfo, field_validator
77
from pydantic.fields import FieldInfo
88
from pydantic_core import ValidationError
9-
from pydantic_settings import BaseSettings, SettingsConfigDict
9+
from pydantic_settings import (
10+
BaseSettings,
11+
EnvSettingsSource,
12+
PydanticBaseSettingsSource,
13+
SettingsConfigDict,
14+
)
1015

1116
_logger = logging.getLogger(__name__)
1217

@@ -46,6 +51,33 @@ def _default_factory():
4651
return _default_factory
4752

4853

54+
class CustomEnvSettingsSource(EnvSettingsSource):
55+
def __init__(self, settings_cls: BaseSettings, env_settings: EnvSettingsSource):
56+
super().__init__(
57+
settings_cls,
58+
env_settings.case_sensitive,
59+
env_settings.env_prefix,
60+
env_settings.env_nested_delimiter,
61+
env_settings.env_ignore_empty,
62+
env_settings.env_parse_none_str,
63+
env_settings.env_parse_enums,
64+
)
65+
66+
def prepare_field_value(
67+
self,
68+
field_name: str,
69+
field: FieldInfo,
70+
value: Any,
71+
value_is_complex: bool, # noqa: FBT001
72+
) -> Any:
73+
prepared_value = super().prepare_field_value(
74+
field_name, field, value, value_is_complex
75+
)
76+
if field.default_factory and field.default is None and prepared_value == {}:
77+
prepared_value = field.default_factory()
78+
return prepared_value
79+
80+
4981
class BaseCustomSettings(BaseSettings):
5082
"""
5183
- Customized configuration for all settings
@@ -126,3 +158,20 @@ def create_from_envs(cls, **overrides):
126158
# Optional to use to make the code more readable
127159
# More explicit and pylance seems to get less confused
128160
return cls(**overrides)
161+
162+
@classmethod
163+
def settings_customise_sources(
164+
cls,
165+
settings_cls: BaseSettings,
166+
init_settings: PydanticBaseSettingsSource,
167+
env_settings: PydanticBaseSettingsSource,
168+
dotenv_settings: PydanticBaseSettingsSource,
169+
file_secret_settings: PydanticBaseSettingsSource,
170+
) -> tuple[PydanticBaseSettingsSource, ...]:
171+
assert env_settings # nosec
172+
return (
173+
init_settings,
174+
CustomEnvSettingsSource(settings_cls, env_settings=env_settings),
175+
dotenv_settings,
176+
file_secret_settings,
177+
)

packages/settings-library/tests/test_base.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
import settings_library.base
1313
from pydantic import BaseModel, ValidationError
1414
from pydantic.fields import Field
15-
from pydantic_settings import BaseSettings
15+
from pydantic_settings import BaseSettings, SettingsConfigDict
1616
from pytest_mock import MockerFixture
1717
from pytest_simcore.helpers.monkeypatch_envs import setenvs_from_envfile
1818
from pytest_simcore.helpers.typing_env import EnvVarsDict
@@ -22,7 +22,6 @@
2222
DefaultFromEnvFactoryError,
2323
)
2424
from settings_library.email import SMTPSettings
25-
from settings_library.utils_logging import MixinLoggingSettings
2625

2726
S2 = json.dumps({"S_VALUE": 2})
2827
S3 = json.dumps({"S_VALUE": 3})
@@ -344,10 +343,12 @@ class SettingsClassThatFailed(BaseCustomSettings):
344343
def test_upgrade_failure_to_pydantic_settings_2_6(
345344
mock_env_devel_environment: EnvVarsDict,
346345
):
347-
class ProblematicSettings(BaseCustomSettings, MixinLoggingSettings):
346+
class ProblematicSettings(BaseCustomSettings):
348347
WEBSERVER_EMAIL: SMTPSettings | None = Field(
349348
json_schema_extra={"auto_default_from_env": True}
350349
)
351350

352-
settings = ProblematicSettings.create_from_envs()
351+
model_config = SettingsConfigDict(nested_model_default_partial_update=True)
352+
353+
settings = ProblematicSettings()
353354
assert settings.WEBSERVER_EMAIL is not None

0 commit comments

Comments
 (0)