Skip to content

Commit 4843c70

Browse files
committed
centralizing IO validation in PleiadesConfig._normalize_config_for_io() and making it strict
1 parent 1213a08 commit 4843c70

File tree

2 files changed

+27
-4
lines changed

2 files changed

+27
-4
lines changed

src/pleiades/utils/config.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -619,6 +619,19 @@ def to_dict(self) -> Dict[str, Any]:
619619
"""Convert configuration to a dictionary."""
620620
return self.model_dump(mode="json")
621621

622+
@classmethod
623+
def _normalize_config_for_io(cls, config_dict: Dict[str, Any]) -> Dict[str, Any]:
624+
"""Normalize config payload before save/load validation.
625+
626+
Enforces strict IO requirements so save/load behavior is consistent:
627+
``fit_routines`` must be present and non-empty.
628+
"""
629+
normalized = dict(config_dict or {})
630+
fit_routines = normalized.get("fit_routines")
631+
if not fit_routines:
632+
raise ValueError("fit_routines must be defined in the config file")
633+
return normalized
634+
622635
def save(self, path: Optional[Path] = None) -> Path:
623636
"""
624637
Save configuration to a YAML file.
@@ -635,9 +648,11 @@ def save(self, path: Optional[Path] = None) -> Path:
635648
# Ensure directory exists
636649
path.parent.mkdir(parents=True, exist_ok=True)
637650

651+
normalized = self._normalize_config_for_io(self.to_dict())
652+
638653
# Save config as YAML
639654
with open(path, "w") as f:
640-
yaml.safe_dump(self.to_dict(), f, sort_keys=False)
655+
yaml.safe_dump(normalized, f, sort_keys=False)
641656

642657
return path
643658

@@ -669,7 +684,8 @@ def load(cls, path: Optional[Path] = None) -> "PleiadesConfig":
669684
@classmethod
670685
def from_dict(cls, config_dict: Dict[str, Any]) -> "PleiadesConfig":
671686
"""Build a configuration from a dictionary."""
672-
return cls.model_validate(config_dict or {}, context={"require_fit_routines": True})
687+
normalized = cls._normalize_config_for_io(config_dict)
688+
return cls.model_validate(normalized, context={"require_fit_routines": True})
673689

674690

675691
class IsotopeConfig(BaseModel):

tests/unit/pleiades/utils/test_utils_config.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -232,10 +232,17 @@ def test_fit_routines_are_normalized_to_typed_models(self):
232232
assert config.fit_routines["fit_2"].dataset_id == "dataset_2"
233233

234234
def test_from_dict_requires_fit_routines(self):
235-
"""Loading from user config should fail when fit_routines are missing."""
236-
with pytest.raises(ValidationError, match="fit_routines must be defined"):
235+
"""Loading from user payload should fail when fit_routines are missing."""
236+
with pytest.raises(ValueError, match="fit_routines must be defined"):
237237
PleiadesConfig.from_dict({"workspace": {"root": "/tmp/pleiades"}})
238238

239+
def test_save_requires_fit_routines(self, tmp_path):
240+
"""Saving config with empty fit_routines should fail."""
241+
config = PleiadesConfig()
242+
save_path = tmp_path / "config.yaml"
243+
with pytest.raises(ValueError, match="fit_routines must be defined"):
244+
config.save(save_path)
245+
239246
def test_isotope_config_normalization_and_defaults(self):
240247
"""Isotope dicts should normalize to IsotopeConfig with default library applied."""
241248
config = PleiadesConfig(

0 commit comments

Comments
 (0)