Skip to content

Commit 4c6fcbd

Browse files
committed
add deep merge functionality to config file sources
1 parent 4433101 commit 4c6fcbd

File tree

4 files changed

+10
-6
lines changed

4 files changed

+10
-6
lines changed

pydantic_settings/sources/base.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from pydantic._internal._typing_extra import ( # type: ignore[attr-defined]
1414
get_origin,
1515
)
16-
from pydantic._internal._utils import is_model_class
16+
from pydantic._internal._utils import deep_update, is_model_class
1717
from pydantic.fields import FieldInfo
1818
from typing_extensions import get_args
1919
from typing_inspection import typing_objects
@@ -193,16 +193,17 @@ def __call__(self) -> dict[str, Any]:
193193

194194

195195
class ConfigFileSourceMixin(ABC):
196-
def _read_files(self, files: PathType | None) -> dict[str, Any]:
196+
def _read_files(self, files: PathType | None, deep_merge: bool = False) -> dict[str, Any]:
197197
if files is None:
198198
return {}
199199
if isinstance(files, (str, os.PathLike)):
200200
files = [files]
201201
vars: dict[str, Any] = {}
202+
update = deep_update if deep_merge else dict.update
202203
for file in files:
203204
file_path = Path(file).expanduser()
204205
if file_path.is_file():
205-
vars.update(self._read_file(file_path))
206+
update(vars, self._read_file(file_path))
206207
return vars
207208

208209
@abstractmethod

pydantic_settings/sources/providers/json.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,15 @@ def __init__(
2626
settings_cls: type[BaseSettings],
2727
json_file: PathType | None = DEFAULT_PATH,
2828
json_file_encoding: str | None = None,
29+
deep_merge: bool = False,
2930
):
3031
self.json_file_path = json_file if json_file != DEFAULT_PATH else settings_cls.model_config.get('json_file')
3132
self.json_file_encoding = (
3233
json_file_encoding
3334
if json_file_encoding is not None
3435
else settings_cls.model_config.get('json_file_encoding')
3536
)
36-
self.json_data = self._read_files(self.json_file_path)
37+
self.json_data = self._read_files(self.json_file_path, deep_merge=deep_merge)
3738
super().__init__(settings_cls, self.json_data)
3839

3940
def _read_file(self, file_path: Path) -> dict[str, Any]:

pydantic_settings/sources/providers/toml.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,10 @@ def __init__(
5050
self,
5151
settings_cls: type[BaseSettings],
5252
toml_file: PathType | None = DEFAULT_PATH,
53+
deep_merge: bool = False,
5354
):
5455
self.toml_file_path = toml_file if toml_file != DEFAULT_PATH else settings_cls.model_config.get('toml_file')
55-
self.toml_data = self._read_files(self.toml_file_path)
56+
self.toml_data = self._read_files(self.toml_file_path, deep_merge=deep_merge)
5657
super().__init__(settings_cls, self.toml_data)
5758

5859
def _read_file(self, file_path: Path) -> dict[str, Any]:

pydantic_settings/sources/providers/yaml.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ def __init__(
4040
yaml_file: PathType | None = DEFAULT_PATH,
4141
yaml_file_encoding: str | None = None,
4242
yaml_config_section: str | None = None,
43+
deep_merge: bool = False,
4344
):
4445
self.yaml_file_path = yaml_file if yaml_file != DEFAULT_PATH else settings_cls.model_config.get('yaml_file')
4546
self.yaml_file_encoding = (
@@ -52,7 +53,7 @@ def __init__(
5253
if yaml_config_section is not None
5354
else settings_cls.model_config.get('yaml_config_section')
5455
)
55-
self.yaml_data = self._read_files(self.yaml_file_path)
56+
self.yaml_data = self._read_files(self.yaml_file_path, deep_merge=deep_merge)
5657

5758
if self.yaml_config_section:
5859
try:

0 commit comments

Comments
 (0)