From e073415109b71d205d0f36d0c4c32f4feca3ccea Mon Sep 17 00:00:00 2001 From: Wout Bittremieux Date: Mon, 11 Dec 2023 11:54:07 +0100 Subject: [PATCH] Check for invalid/missin config entries (#268) * Refactor config checking - More efficient checking for unknown and missing config entries (no needless conversions/creations of sets and lists). - Avoid creating temporary files in root directories during unit testing. - Update outdated test. * Add unit test fix --- casanovo/config.py | 25 ++++++++++--------- tests/unit_tests/test_config.py | 44 ++++++++++++++++----------------- 2 files changed, 35 insertions(+), 34 deletions(-) diff --git a/casanovo/config.py b/casanovo/config.py index c07073d6..c175eef1 100644 --- a/casanovo/config.py +++ b/casanovo/config.py @@ -83,17 +83,20 @@ def __init__(self, config_file: Optional[str] = None): else: with Path(config_file).open() as f_in: self._user_config = yaml.safe_load(f_in) - # check for missing entries in config file - if len(self._user_config.keys()) < len(self._params.keys()): - keys_set = set(self._params.keys()) - users_set = set(self._user_config.keys()) - missing = list(keys_set - users_set) - raise KeyError(f"Missing expected entry {missing}") - # detect unrecognized config file entries - keys = list(self._params.keys()) - for key, val in self._user_config.items(): - if key not in keys: - raise KeyError(f"Unrecognized config file entry {key}") + # Check for missing entries in config file. + config_missing = self._params.keys() - self._user_config.keys() + if len(config_missing) > 0: + raise KeyError( + "Missing expected config option(s): " + f"{', '.join(config_missing)}" + ) + # Check for unrecognized config file entries. + config_unknown = self._user_config.keys() - self._params.keys() + if len(config_unknown) > 0: + raise KeyError( + "Unrecognized config option(s): " + f"{', '.join(config_unknown)}" + ) # Validate: for key, val in self._config_types.items(): self.validate_param(key, val) diff --git a/tests/unit_tests/test_config.py b/tests/unit_tests/test_config.py index fd8ed22e..7a0d7a26 100644 --- a/tests/unit_tests/test_config.py +++ b/tests/unit_tests/test_config.py @@ -1,8 +1,9 @@ """Test configuration loading""" -from casanovo.config import Config import pytest import yaml +from casanovo.config import Config + def test_default(): """Test that loading the default works""" @@ -14,27 +15,24 @@ def test_default(): def test_override(tmp_path, tiny_config): - """Test overriding the default""" - yml = tmp_path / "test.yml" - with yml.open("w+") as f_out: - f_out.write( - """random_seed: 42 -top_match: 3 -residues: - W: 1 - O: 2 - U: 3 - T: 4 -""" - ) - - with open(tiny_config, "r") as read_file: - contents = yaml.safe_load(read_file) - contents["random_seed_"] = 354 - - with open("output.yml", "w") as write_file: - yaml.safe_dump(contents, write_file) + # Test expected config option is missing. + filename = str(tmp_path / "config_missing.yml") + with open(tiny_config, "r") as f_in, open(filename, "w") as f_out: + cfg = yaml.safe_load(f_in) + # Remove config option. + del cfg["random_seed"] + yaml.safe_dump(cfg, f_out) + with pytest.raises(KeyError): - config = Config("output.yml") + Config(filename) + + # Test invalid config option is present. + filename = str(tmp_path / "config_invalid.yml") + with open(tiny_config, "r") as f_in, open(filename, "w") as f_out: + cfg = yaml.safe_load(f_in) + # Insert invalid config option. + cfg["random_seed_"] = 354 + yaml.safe_dump(cfg, f_out) + with pytest.raises(KeyError): - config = Config(yml) + Config(filename)