Repository: python-wheel-build/fromager

Issue:
Undefined variable in env vars no longer raises an error
Fromager no longer raises an error when it encounters and undefined variable in an `env` vars block. Instead of failing it uses `None`. This hides typos in settings files.

Current behavior:
```python
>>> from fromager.packagesettings import substitute_template
>>> substitute_template("${DEFAULT:-default} ${UNKOWN}", {})
'default None'
```

Expected behavior:
Fromager should fail with `KeyError: 'UNKNOWN'`

Discussion:

Solution patch:
diff --git a/src/fromager/packagesettings.py b/src/fromager/packagesettings.py
index ff88c62..685f900 100644
--- a/src/fromager/packagesettings.py
+++ b/src/fromager/packagesettings.py
@@ -457,11 +457,20 @@ def substitute_template(value: str, template_env: dict[str, str]) -> str:
     for mo in _DEFAULT_PATTERN_RE.finditer(value):
         modict = mo.groupdict()
         name = modict["name"]
-        # add to local default, keep existing default
-        localdefault.setdefault(name, modict["default"])
-        # remove ":-default"
-        value = value.replace(mo.group(0), f"${{{name}}}")
-    return string.Template(value).substitute(localdefault)
+        default = modict["default"]
+        # Only set the default if one is explicitly provided.
+        # This ensures that undefined variables without defaults
+        # will raise KeyError later
+        if default is not None:
+            localdefault.setdefault(name, default)
+            # Replace ${var:-default} with ${var}
+            value = value.replace(mo.group(0), f"${{{name}}}")
+    try:
+        return string.Template(value).substitute(localdefault)
+    except KeyError as e:
+        raise ValueError(
+            f"Undefined environment variable {e!r} referenced in expression {value!r}"
+        ) from e
 
 
 def get_cpu_count() -> int:


Test patch:
diff --git a/tests/test_packagesettings.py b/tests/test_packagesettings.py
index fbe1422..a84415c 100644
--- a/tests/test_packagesettings.py
+++ b/tests/test_packagesettings.py
@@ -468,3 +468,14 @@ def test_parallel_jobs(
 )
 def test_substitute_template(value: str, template_env: dict[str, str], expected: str):
     assert substitute_template(value, template_env) == expected
+
+
+def test_substitute_template_key_error():
+    # This test expects a ValueError to be raised by substitute_template
+    with pytest.raises(ValueError) as excinfo:
+        substitute_template("${DEFAULT:-default} ${UNKNOWN}", {})
+    # Verify that the error message matches the expected message
+    assert (
+        str(excinfo.value)
+        == "Undefined environment variable KeyError('UNKNOWN') referenced in expression '${DEFAULT} ${UNKNOWN}'"
+    )