diff --git a/promptlens/loaders/json_loader.py b/promptlens/loaders/json_loader.py index d18d69d..a240336 100644 --- a/promptlens/loaders/json_loader.py +++ b/promptlens/loaders/json_loader.py @@ -36,6 +36,11 @@ def load(self, path: str) -> GoldenSet: except json.JSONDecodeError as e: raise ValueError(f"Invalid JSON in {path}: {e}") + if not isinstance(data, dict): + raise ValueError( + f"Invalid golden set format in {path}: root value must be a JSON object" + ) + try: golden_set = GoldenSet(**data) logger.info( diff --git a/promptlens/loaders/yaml_loader.py b/promptlens/loaders/yaml_loader.py index e24365f..6a1a13e 100644 --- a/promptlens/loaders/yaml_loader.py +++ b/promptlens/loaders/yaml_loader.py @@ -39,6 +39,11 @@ def load(self, path: str) -> GoldenSet: if data is None: raise ValueError(f"Empty YAML file: {path}") + if not isinstance(data, dict): + raise ValueError( + f"Invalid golden set format in {path}: root value must be a YAML mapping" + ) + try: golden_set = GoldenSet(**data) logger.info( diff --git a/tests/test_loader_root_validation.py b/tests/test_loader_root_validation.py new file mode 100644 index 0000000..3760b00 --- /dev/null +++ b/tests/test_loader_root_validation.py @@ -0,0 +1,22 @@ +import json + +import pytest + +from promptlens.loaders.json_loader import JSONLoader +from promptlens.loaders.yaml_loader import YAMLLoader + + +def test_json_loader_rejects_non_object_root(tmp_path): + p = tmp_path / "golden.json" + p.write_text(json.dumps([{"id": "tc-1"}]), encoding="utf-8") + + with pytest.raises(ValueError, match="root value must be a JSON object"): + JSONLoader().load(str(p)) + + +def test_yaml_loader_rejects_non_mapping_root(tmp_path): + p = tmp_path / "golden.yaml" + p.write_text("- id: tc-1\n", encoding="utf-8") + + with pytest.raises(ValueError, match="root value must be a YAML mapping"): + YAMLLoader().load(str(p))