|
|
@@ -313,6 +313,32 @@ class Variable:
|
|
|
|
|
|
return " — ".join(hints) if hints else None
|
|
|
|
|
|
+ def is_required(self) -> bool:
|
|
|
+ """Check if this variable requires a value (cannot be empty/None).
|
|
|
+
|
|
|
+ A variable is considered required if:
|
|
|
+ - It doesn't have a default value (value is None)
|
|
|
+ - It's not marked as autogenerated (which can be empty and generated later)
|
|
|
+ - It's not a boolean type (booleans default to False if not set)
|
|
|
+
|
|
|
+ Returns:
|
|
|
+ True if the variable must have a non-empty value, False otherwise
|
|
|
+ """
|
|
|
+ # Autogenerated variables can be empty (will be generated later)
|
|
|
+ if self.autogenerated:
|
|
|
+ return False
|
|
|
+
|
|
|
+ # Boolean variables always have a value (True or False)
|
|
|
+ if self.type == "bool":
|
|
|
+ return False
|
|
|
+
|
|
|
+ # Variables with a default value are not required
|
|
|
+ if self.value is not None:
|
|
|
+ return False
|
|
|
+
|
|
|
+ # No default value and not autogenerated = required
|
|
|
+ return True
|
|
|
+
|
|
|
def clone(self, update: Optional[Dict[str, Any]] = None) -> 'Variable':
|
|
|
"""Create a deep copy of the variable with optional field updates.
|
|
|
|
|
|
@@ -879,9 +905,10 @@ class VariableCollection:
|
|
|
logger.debug(f"Skipping validation for autogenerated variable: '{section.key}.{var_name}'")
|
|
|
continue
|
|
|
|
|
|
- # If value is None, treat as missing
|
|
|
+ # If value is None and the variable is required, report as missing
|
|
|
if variable.value is None:
|
|
|
- errors.append(f"{section.key}.{var_name} (missing)")
|
|
|
+ if variable.is_required():
|
|
|
+ errors.append(f"{section.key}.{var_name} (required - no default provided)")
|
|
|
continue
|
|
|
|
|
|
# Attempt to convert/validate typed value
|
|
|
@@ -889,10 +916,13 @@ class VariableCollection:
|
|
|
|
|
|
# For non-boolean types, treat None or empty string as invalid
|
|
|
if variable.type not in ("bool",) and (typed is None or typed == ""):
|
|
|
- errors.append(f"{section.key}.{var_name} (empty)")
|
|
|
+ if variable.is_required():
|
|
|
+ errors.append(f"{section.key}.{var_name} (required - cannot be empty)")
|
|
|
+ else:
|
|
|
+ errors.append(f"{section.key}.{var_name} (empty)")
|
|
|
|
|
|
except ValueError as e:
|
|
|
- errors.append(f"{section.key}.{var_name} (invalid: {e})")
|
|
|
+ errors.append(f"{section.key}.{var_name} (invalid format: {e})")
|
|
|
|
|
|
if errors:
|
|
|
error_msg = "Variable validation failed: " + ", ".join(errors)
|