Skip to content

Commit 3e39401

Browse files
committed
feat: Add 'yaml_nested_key' option
1 parent 1874740 commit 3e39401

File tree

3 files changed

+40
-0
lines changed

3 files changed

+40
-0
lines changed

pydantic_settings/main.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ class SettingsConfigDict(ConfigDict, total=False):
6262
json_file_encoding: str | None
6363
yaml_file: PathType | None
6464
yaml_file_encoding: str | None
65+
yaml_nested_key: str | None
6566
pyproject_toml_depth: int
6667
"""
6768
Number of levels **up** from the current working directory to attempt to find a pyproject.toml
@@ -446,6 +447,7 @@ def _settings_build_values(
446447
json_file_encoding=None,
447448
yaml_file=None,
448449
yaml_file_encoding=None,
450+
yaml_nested_key=None,
449451
toml_file=None,
450452
secrets_dir=None,
451453
protected_namespaces=('model_validate', 'model_dump', 'settings_customise_sources'),

pydantic_settings/sources/providers/yaml.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,21 @@ def __init__(
3939
settings_cls: type[BaseSettings],
4040
yaml_file: PathType | None = DEFAULT_PATH,
4141
yaml_file_encoding: str | None = None,
42+
yaml_nested_key: str | None = None,
4243
):
4344
self.yaml_file_path = yaml_file if yaml_file != DEFAULT_PATH else settings_cls.model_config.get('yaml_file')
4445
self.yaml_file_encoding = (
4546
yaml_file_encoding
4647
if yaml_file_encoding is not None
4748
else settings_cls.model_config.get('yaml_file_encoding')
4849
)
50+
self.yaml_nested_key = (
51+
yaml_nested_key if yaml_nested_key is not None else settings_cls.model_config.get('yaml_nested_key')
52+
)
4953
self.yaml_data = self._read_files(self.yaml_file_path)
54+
55+
if self.yaml_nested_key:
56+
self.yaml_data = self.yaml_data[self.yaml_nested_key]
5057
super().__init__(settings_cls, self.yaml_data)
5158

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

tests/test_source_yaml.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,3 +166,34 @@ def settings_customise_sources(
166166

167167
s = Settings()
168168
assert s.model_dump() == {'yaml3': 3, 'yaml4': 4}
169+
170+
171+
@pytest.mark.skipif(yaml is None, reason='pyYAML is not installed')
172+
def test_yaml_nested_key(tmp_path):
173+
p = tmp_path / '.env'
174+
p.write_text(
175+
"""
176+
foobar: "Hello"
177+
nested:
178+
nested_field: "world!"
179+
"""
180+
)
181+
182+
class Settings(BaseSettings):
183+
nested_field: str
184+
185+
model_config = SettingsConfigDict(yaml_file=p, yaml_nested_key='nested')
186+
187+
@classmethod
188+
def settings_customise_sources(
189+
cls,
190+
settings_cls: type[BaseSettings],
191+
init_settings: PydanticBaseSettingsSource,
192+
env_settings: PydanticBaseSettingsSource,
193+
dotenv_settings: PydanticBaseSettingsSource,
194+
file_secret_settings: PydanticBaseSettingsSource,
195+
) -> tuple[PydanticBaseSettingsSource, ...]:
196+
return (YamlConfigSettingsSource(settings_cls),)
197+
198+
s = Settings()
199+
assert s.nested_field == 'world!'

0 commit comments

Comments
 (0)