|
6 | 6 | from pydantic import ValidationInfo, field_validator |
7 | 7 | from pydantic.fields import FieldInfo |
8 | 8 | 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 | +) |
10 | 15 |
|
11 | 16 | _logger = logging.getLogger(__name__) |
12 | 17 |
|
@@ -46,6 +51,33 @@ def _default_factory(): |
46 | 51 | return _default_factory |
47 | 52 |
|
48 | 53 |
|
| 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 | + |
49 | 81 | class BaseCustomSettings(BaseSettings): |
50 | 82 | """ |
51 | 83 | - Customized configuration for all settings |
@@ -126,3 +158,20 @@ def create_from_envs(cls, **overrides): |
126 | 158 | # Optional to use to make the code more readable |
127 | 159 | # More explicit and pylance seems to get less confused |
128 | 160 | 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 | + ) |
0 commit comments