diff --git a/src/corelibs/config_handling/settings_loader.py b/src/corelibs/config_handling/settings_loader.py index d28f0a7..4405db3 100644 --- a/src/corelibs/config_handling/settings_loader.py +++ b/src/corelibs/config_handling/settings_loader.py @@ -93,6 +93,8 @@ class SettingsLoader: entry_split_char: dict[str, str] = {} # entries that should be converted entry_convert: dict[str, str] = {} + # no args to set + args_none: list[str] = [] # all the settings for the config id given settings: dict[str, dict[str, Any]] = { config_id: {}, @@ -162,6 +164,8 @@ class SettingsLoader: f"[!] In [{config_id}] the split character setup for entry failed: {check}: {e}", 'CRITICAL' )) from e + if check == "args:no": + args_none.append(key) if skip: continue settings[config_id][key] = [ @@ -185,9 +189,15 @@ class SettingsLoader: error: bool = False for entry, validate in config_validate.items(): # if we have command line option set, this one overrides config - if self.__get_arg(entry): + if (args_entry := self.__get_arg(entry)) is not None: self.__print(f"[*] Command line option override for: {entry}", 'WARNING') - settings[config_id][entry] = self.args.get(entry) + if ( + entry not in args_none and + (isinstance(args_entry, list) and entry_split_char.get(entry)) or + (not isinstance(args_entry, list) and not entry_split_char.get(entry)) + ): + # args is list, but entry has not split, do not set + settings[config_id][entry] = args_entry # validate checks for check in validate: # CHECKS diff --git a/test-run/config_handling/config/settings.ini b/test-run/config_handling/config/settings.ini index 69efe5e..7d4184a 100644 --- a/test-run/config_handling/config/settings.ini +++ b/test-run/config_handling/config/settings.ini @@ -2,6 +2,10 @@ foo=bar foobar=1 bar=st +arg_overload=should_not_be_set_because_of_command_line_is_list +arg_overload_list=too,be,long +arg_overload_not_set=this should not be set because of override flag +just_values=too,be,long some_match=foo some_match_list=foo,bar test_list=a,b,c,d f, g h diff --git a/test-run/config_handling/settings_loader.py b/test-run/config_handling/settings_loader.py index 3e24fad..64da6a8 100644 --- a/test-run/config_handling/settings_loader.py +++ b/test-run/config_handling/settings_loader.py @@ -39,7 +39,10 @@ def main(): sl = SettingsLoader( { - 'foo': 'OVERLOAD' + 'foo': 'OVERLOAD', + 'arg_overload': ['should', 'not', 'be', 'set'], + 'arg_overload_list': ['overload', 'this', 'list'], + 'arg_overload_not_set': "DO_NOT_SET", }, ROOT_PATH.joinpath(CONFIG_DIR, CONFIG_FILE), log=log @@ -53,6 +56,8 @@ def main(): "foo": ["mandatory:yes"], "foobar": ["check:int"], "bar": ["mandatory:yes"], + "arg_overload_list": ["split:,",], + "arg_overload_not_set": ["args:no"], "some_match": ["matching:foo|bar"], "some_match_list": ["split:,", "matching:foo|bar"], "test_list": [ diff --git a/tests/unit/config_handling/test_settings_loader.py b/tests/unit/config_handling/test_settings_loader.py index f4dd966..a7c2145 100644 --- a/tests/unit/config_handling/test_settings_loader.py +++ b/tests/unit/config_handling/test_settings_loader.py @@ -528,6 +528,123 @@ class TestLoadSettings: captured = capsys.readouterr() assert "Command line option override" in captured.out + def test_load_settings_args_no_flag(self, tmp_path: Path, capsys: CaptureFixture[str]): + """Test args:no flag with list argument that has split""" + config_file = tmp_path / "test.ini" + config_file.write_text("[TestSection]\nvalue=a,b,c\n") + + loader = SettingsLoader( + args={"value": ["x", "y", "z"]}, + config_file=config_file + ) + result = loader.load_settings( + "TestSection", + {"value": ["args:no", "split:,"]} + ) + + # With args:no and split defined for list args, should use config value + assert result["value"] == ["a", "b", "c"] + captured = capsys.readouterr() + # Message is printed but args:no prevents the override + assert "Command line option override" in captured.out + + def test_load_settings_args_list_no_split(self, tmp_path: Path, capsys: CaptureFixture[str]): + """Test that list arguments without split entry are skipped""" + config_file = tmp_path / "test.ini" + config_file.write_text("[TestSection]\nvalue=config_value\n") + + loader = SettingsLoader( + args={"value": ["arg1", "arg2", "arg3"]}, + config_file=config_file + ) + result = loader.load_settings( + "TestSection", + {"value": []} + ) + + # Should keep config value since args is list but no split defined + assert result["value"] == "config_value" + captured = capsys.readouterr() + # Message is printed but list without split prevents the override + assert "Command line option override" in captured.out + + def test_load_settings_args_list_with_split(self, tmp_path: Path, capsys: CaptureFixture[str]): + """Test that list arguments with split entry are applied""" + config_file = tmp_path / "test.ini" + config_file.write_text("[TestSection]\nvalue=a,b,c\n") + + loader = SettingsLoader( + args={"value": ["arg1", "arg2", "arg3"]}, + config_file=config_file + ) + result = loader.load_settings( + "TestSection", + {"value": ["split:,"]} + ) + + # Should use args value since split is defined + assert result["value"] == ["arg1", "arg2", "arg3"] + captured = capsys.readouterr() + assert "Command line option override" in captured.out + + def test_load_settings_args_no_with_mandatory(self, tmp_path: Path, capsys: CaptureFixture[str]): + """Test args:no with mandatory field and list args with split""" + config_file = tmp_path / "test.ini" + config_file.write_text("[TestSection]\nvalue=config1,config2\n") + + loader = SettingsLoader( + args={"value": ["arg1", "arg2"]}, + config_file=config_file + ) + result = loader.load_settings( + "TestSection", + {"value": ["mandatory:yes", "args:no", "split:,"]} + ) + + # Should use config value because of args:no with list args and split + assert result["value"] == ["config1", "config2"] + captured = capsys.readouterr() + # Message is printed but args:no prevents the override + assert "Command line option override" in captured.out + + def test_load_settings_args_no_with_mandatory_valid(self, tmp_path: Path, capsys: CaptureFixture[str]): + """Test args:no with string args still allows override (current behavior)""" + config_file = tmp_path / "test.ini" + config_file.write_text("[TestSection]\nvalue=config_value\n") + + loader = SettingsLoader( + args={"value": "arg_value"}, + config_file=config_file + ) + result = loader.load_settings( + "TestSection", + {"value": ["mandatory:yes", "args:no"]} + ) + + # Current behavior: string args without split still override even with args:no + assert result["value"] == "arg_value" + captured = capsys.readouterr() + assert "Command line option override" in captured.out + + def test_load_settings_args_string_no_split(self, tmp_path: Path, capsys: CaptureFixture[str]): + """Test that string arguments without split entry work normally""" + config_file = tmp_path / "test.ini" + config_file.write_text("[TestSection]\nvalue=config_value\n") + + loader = SettingsLoader( + args={"value": "arg_value"}, + config_file=config_file + ) + result = loader.load_settings( + "TestSection", + {"value": []} + ) + + # Should use args value for non-list args + assert result["value"] == "arg_value" + captured = capsys.readouterr() + assert "Command line option override" in captured.out + def test_load_settings_no_config_file_with_args(self, tmp_path: Path): """Test loading settings without config file but with mandatory args""" config_file = tmp_path / "missing.ini" @@ -704,5 +821,48 @@ class TestComplexScenarios: assert result["emails"] == "test@example.com" assert result["date"] == "2025-01-15" + def test_args_no_and_list_skip_combination(self, tmp_path: Path, capsys: CaptureFixture[str]): + """Test combination of args:no flag and list argument skip behavior""" + config_file = tmp_path / "test.ini" + config_file.write_text( + "[Settings]\n" + "no_override=a,b,c\n" + "list_no_split=config_list\n" + "list_with_split=x,y,z\n" + "normal=config_normal\n" + ) + + loader = SettingsLoader( + args={ + "no_override": ["arg1", "arg2"], + "list_no_split": ["arg1", "arg2"], + "list_with_split": ["p", "q", "r"], + "normal": "arg_normal" + }, + config_file=config_file + ) + result = loader.load_settings( + "Settings", + { + "no_override": ["args:no", "split:,"], + "list_no_split": [], + "list_with_split": ["split:,"], + "normal": [] + } + ) + + # Should use config value due to args:no with list args and split + assert result["no_override"] == ["a", "b", "c"] + # Should use config value because args is list without split + assert result["list_no_split"] == "config_list" + # Should use args value because split is defined and no args:no + assert result["list_with_split"] == ["p", "q", "r"] + # Should use args value normally (string arg without split) + assert result["normal"] == "arg_normal" + + captured = capsys.readouterr() + # Should see override messages (even though list_no_split prints, it doesn't apply) + assert "Command line option override" in captured.out + # __END__