Update settings loader with skip argument set if not matching settings type or ignore flag is set

We have "args:no" that can be set to avoid override from arguments.
Also arguments that do not match the exepected type are not loaded
This commit is contained in:
Clemens Schwaighofer
2025-11-19 19:01:29 +09:00
parent baca79ce82
commit 1f7f4b8d53
4 changed files with 182 additions and 3 deletions

View File

@@ -93,6 +93,8 @@ class SettingsLoader:
entry_split_char: dict[str, str] = {} entry_split_char: dict[str, str] = {}
# entries that should be converted # entries that should be converted
entry_convert: dict[str, str] = {} entry_convert: dict[str, str] = {}
# no args to set
args_none: list[str] = []
# all the settings for the config id given # all the settings for the config id given
settings: dict[str, dict[str, Any]] = { settings: dict[str, dict[str, Any]] = {
config_id: {}, config_id: {},
@@ -162,6 +164,8 @@ class SettingsLoader:
f"[!] In [{config_id}] the split character setup for entry failed: {check}: {e}", f"[!] In [{config_id}] the split character setup for entry failed: {check}: {e}",
'CRITICAL' 'CRITICAL'
)) from e )) from e
if check == "args:no":
args_none.append(key)
if skip: if skip:
continue continue
settings[config_id][key] = [ settings[config_id][key] = [
@@ -185,9 +189,15 @@ class SettingsLoader:
error: bool = False error: bool = False
for entry, validate in config_validate.items(): for entry, validate in config_validate.items():
# if we have command line option set, this one overrides config # 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') 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 # validate checks
for check in validate: for check in validate:
# CHECKS # CHECKS

View File

@@ -2,6 +2,10 @@
foo=bar foo=bar
foobar=1 foobar=1
bar=st 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=foo
some_match_list=foo,bar some_match_list=foo,bar
test_list=a,b,c,d f, g h test_list=a,b,c,d f, g h

View File

@@ -39,7 +39,10 @@ def main():
sl = SettingsLoader( 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), ROOT_PATH.joinpath(CONFIG_DIR, CONFIG_FILE),
log=log log=log
@@ -53,6 +56,8 @@ def main():
"foo": ["mandatory:yes"], "foo": ["mandatory:yes"],
"foobar": ["check:int"], "foobar": ["check:int"],
"bar": ["mandatory:yes"], "bar": ["mandatory:yes"],
"arg_overload_list": ["split:,",],
"arg_overload_not_set": ["args:no"],
"some_match": ["matching:foo|bar"], "some_match": ["matching:foo|bar"],
"some_match_list": ["split:,", "matching:foo|bar"], "some_match_list": ["split:,", "matching:foo|bar"],
"test_list": [ "test_list": [

View File

@@ -528,6 +528,123 @@ class TestLoadSettings:
captured = capsys.readouterr() captured = capsys.readouterr()
assert "Command line option override" in captured.out 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): def test_load_settings_no_config_file_with_args(self, tmp_path: Path):
"""Test loading settings without config file but with mandatory args""" """Test loading settings without config file but with mandatory args"""
config_file = tmp_path / "missing.ini" config_file = tmp_path / "missing.ini"
@@ -704,5 +821,48 @@ class TestComplexScenarios:
assert result["emails"] == "test@example.com" assert result["emails"] == "test@example.com"
assert result["date"] == "2025-01-15" 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__ # __END__