]> git.ipfire.org Git - thirdparty/mkosi.git/commitdiff
Don't use default value if optional settings are set to none
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Thu, 24 Apr 2025 12:31:32 +0000 (14:31 +0200)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Thu, 24 Apr 2025 13:16:11 +0000 (15:16 +0200)
Just like it's possible to disable usage of default values for collection
based settings, we should also support it for optional settings.
This can be used to disable usage of the tools tree even if mkosi.tools.conf
exists by setting ToolsTree= in mkosi.local.conf.

mkosi/config.py
tests/test_config.py

index b1f8d2b14cb0a1afd6981d5e2d637da59388f788..ec418b4e6c4b39ec1281481f10668b967b8d93fe 100644 (file)
@@ -1792,8 +1792,8 @@ class Args:
 
     @classmethod
     @functools.lru_cache(maxsize=1)
-    def fields(cls) -> set[str]:
-        return {f.name for f in dataclasses.fields(cls)}
+    def fields(cls) -> dict[str, dataclasses.Field[Any]]:
+        return {f.name: f for f in dataclasses.fields(cls)}
 
     @classmethod
     def from_namespace(cls, ns: dict[str, Any]) -> "Args":
@@ -2190,8 +2190,8 @@ class Config:
 
     @classmethod
     @functools.lru_cache(maxsize=1)
-    def fields(cls) -> set[str]:
-        return {f.name for f in dataclasses.fields(cls)}
+    def fields(cls) -> dict[str, dataclasses.Field[Any]]:
+        return {f.name: f for f in dataclasses.fields(cls)}
 
     @classmethod
     def from_dict(cls, ns: dict[str, Any]) -> "Config":
@@ -4684,8 +4684,18 @@ class ParseContext:
         ):
             return v
 
-        if (setting.dest in self.cli or setting.dest in self.config) and isinstance(
-            setting.parse(None, None), (dict, list, set)
+        # If the type is a collection or optional and the setting was set explicitly, don't use the default
+        # value.
+        fieldname = (
+            setting.dest.removeprefix("tools_tree_") if setting.scope == SettingScope.tools else setting.dest
+        )
+        field = Config.fields().get(fieldname)
+        origin = typing.get_origin(field.type) if field else None
+        args = typing.get_args(field.type) if field else []
+        if (
+            (setting.dest in self.cli or setting.dest in self.config)
+            and field
+            and (origin in (dict, list, str) or (origin is typing.Union and type(None) in args))
         ):
             default = setting.parse(None, None)
         elif setting.dest in self.defaults:
index bc52cd1c7e69c85e265713efeef53417150fd221..ff9c2b9febd0982962e9562793c24ad705f18cce 100644 (file)
@@ -450,6 +450,20 @@ def test_override_default(tmp_path: Path) -> None:
     assert config.tools_tree is None
     assert "MY_KEY" not in config.environment
 
+    (d / "mkosi.tools.conf").touch()
+
+    (d / "mkosi.local.conf").write_text(
+        """\
+        [Build]
+        ToolsTree=
+        """
+    )
+
+    with chdir(d):
+        _, _, [config] = parse_config([])
+
+    assert config.tools_tree is None
+
 
 def test_local_config(tmp_path: Path) -> None:
     d = tmp_path