Skip to content

Commit e54abd1

Browse files
switch to safe_load; create load_yaml helper function
1 parent 5898683 commit e54abd1

File tree

4 files changed

+49
-9
lines changed

4 files changed

+49
-9
lines changed

src/layered_config_tree/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,4 @@
1414
DuplicatedConfigurationError,
1515
ImproperAccessError,
1616
)
17-
from layered_config_tree.main import ConfigNode, LayeredConfigTree
17+
from layered_config_tree.main import ConfigNode, LayeredConfigTree, load_yaml

src/layered_config_tree/main.py

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -464,17 +464,17 @@ def _coerce(
464464
elif (isinstance(data, str) and data.endswith((".yaml", ".yml"))) or isinstance(
465465
data, Path
466466
):
467+
# 'data' is a filepath to a yaml file
467468
source = source if source else str(data)
468-
with open(data) as f:
469-
data_file = f.read()
470-
coerced_data = yaml.full_load(data_file)
469+
coerced_data = load_yaml(data)
471470
if not isinstance(coerced_data, dict):
472471
raise ValueError(
473472
f"Loaded yaml file {coerced_data} should be a dictionary but is type {type(coerced_data)}"
474473
)
475474
return coerced_data, source
476475
elif isinstance(data, str):
477-
data = yaml.full_load(data)
476+
# 'data' is a yaml string
477+
data = load_yaml(data)
478478
if not isinstance(data, dict):
479479
raise ValueError(
480480
f"Loaded yaml file {data} should be a dictionary but is type {type(data)}"
@@ -671,3 +671,39 @@ def __str__(self) -> str:
671671

672672
def __eq__(self, other: object) -> bool:
673673
raise NotImplementedError
674+
675+
676+
# class UniqueKeyHandler(SafeLoader):
677+
# ...
678+
679+
680+
def load_yaml(data: str | Path) -> dict[str, Any]:
681+
"""Loads a YAML filepath or string into a dictionary.
682+
683+
Parameters
684+
----------
685+
data
686+
The YAML content to load. This can be a file path to a YAML file or a string
687+
containing YAML-formatted text.
688+
689+
Returns
690+
-------
691+
A dictionary representation of the loaded YAML content.
692+
693+
Notes
694+
-----
695+
If `data` is a Path object or a string that ends with ".yaml" or ".yml", it is
696+
treated as a filepath and this function loads the file. Otherwise, `data` is a
697+
string that does _not_ end in ".yaml" or ".yml" and it is treated as YAML-formatted
698+
text which is loaded directly into a dictionary.
699+
"""
700+
701+
if (isinstance(data, str) and data.endswith((".yaml", ".yml"))) or isinstance(data, Path):
702+
# 'data' is a filepath to a yaml file
703+
with open(data) as f:
704+
data_file = f.read()
705+
data_dict = yaml.safe_load(data_file)
706+
else:
707+
# 'data' is a yaml string
708+
data_dict = yaml.safe_load(data)
709+
return data_dict

tests/test_basic_functionality.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
DuplicatedConfigurationError,
1515
ImproperAccessError,
1616
LayeredConfigTree,
17+
load_yaml,
1718
)
1819

1920

@@ -500,8 +501,7 @@ def test_to_dict_dict() -> None:
500501

501502
def test_to_dict_yaml(test_spec: Path) -> None:
502503
lct = LayeredConfigTree(str(test_spec))
503-
with test_spec.open() as f:
504-
yaml_config = yaml.full_load(f)
504+
yaml_config = load_yaml(test_spec)
505505
assert yaml_config == lct.to_dict()
506506

507507

tests/test_ingestion.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
from pathlib import Path
22

3+
import pytest
4+
35
from layered_config_tree import LayeredConfigTree
46

57
TEST_YAML_ONE = """
@@ -21,12 +23,14 @@ def test_load_yaml_string() -> None:
2123
assert lct.test_section2.test_key == "test_value3"
2224

2325

24-
def test_load_yaml_file(tmp_path: Path) -> None:
26+
@pytest.mark.parametrize("path_type", [str, Path])
27+
def test_load_yaml_file(tmp_path: Path, path_type: type[str | Path]) -> None:
2528
tmp_file = tmp_path / "test_file.yaml"
2629
tmp_file.write_text(TEST_YAML_ONE)
2730

2831
lct = LayeredConfigTree()
29-
lct.update(str(tmp_file))
32+
filepath_to_test = str(tmp_file) if path_type is str else tmp_file
33+
lct.update(filepath_to_test)
3034

3135
assert lct.test_section.test_key == "test_value"
3236
assert lct.test_section.test_key2 == "test_value2"

0 commit comments

Comments
 (0)