ASP-based solver: don't error for type mismatch on preferences (#41138)
This commit discards type mismatches or failures to validate a package preference during concretization. The values discarded are logged as debug level messages. It also adds a config audit to help users spot misconfigurations in packages.yaml preferences.
This commit is contained in:
parent
f39a1e5fc8
commit
4f7cce68b8
3 changed files with 65 additions and 1 deletions
|
@ -286,6 +286,54 @@ def make_error(attribute_name, config_data, summary):
|
|||
return errors
|
||||
|
||||
|
||||
@config_packages
|
||||
def _avoid_mismatched_variants(error_cls):
|
||||
"""Warns if variant preferences have mismatched types or names."""
|
||||
errors = []
|
||||
packages_yaml = spack.config.CONFIG.get_config("packages")
|
||||
|
||||
def make_error(config_data, summary):
|
||||
s = io.StringIO()
|
||||
s.write("Occurring in the following file:\n")
|
||||
syaml.dump_config(config_data, stream=s, blame=True)
|
||||
return error_cls(summary=summary, details=[s.getvalue()])
|
||||
|
||||
for pkg_name in packages_yaml:
|
||||
# 'all:' must be more forgiving, since it is setting defaults for everything
|
||||
if pkg_name == "all" or "variants" not in packages_yaml[pkg_name]:
|
||||
continue
|
||||
|
||||
preferences = packages_yaml[pkg_name]["variants"]
|
||||
if not isinstance(preferences, list):
|
||||
preferences = [preferences]
|
||||
|
||||
for variants in preferences:
|
||||
current_spec = spack.spec.Spec(variants)
|
||||
pkg_cls = spack.repo.PATH.get_pkg_class(pkg_name)
|
||||
for variant in current_spec.variants.values():
|
||||
# Variant does not exist at all
|
||||
if variant.name not in pkg_cls.variants:
|
||||
summary = (
|
||||
f"Setting a preference for the '{pkg_name}' package to the "
|
||||
f"non-existing variant '{variant.name}'"
|
||||
)
|
||||
errors.append(make_error(preferences, summary))
|
||||
continue
|
||||
|
||||
# Variant cannot accept this value
|
||||
s = spack.spec.Spec(pkg_name)
|
||||
try:
|
||||
s.update_variant_validate(variant.name, variant.value)
|
||||
except Exception:
|
||||
summary = (
|
||||
f"Setting the variant '{variant.name}' of the '{pkg_name}' package "
|
||||
f"to the invalid value '{str(variant)}'"
|
||||
)
|
||||
errors.append(make_error(preferences, summary))
|
||||
|
||||
return errors
|
||||
|
||||
|
||||
#: Sanity checks on package directives
|
||||
package_directives = AuditClass(
|
||||
group="packages",
|
||||
|
|
|
@ -1828,7 +1828,13 @@ def preferred_variants(self, pkg_name):
|
|||
|
||||
# perform validation of the variant and values
|
||||
spec = spack.spec.Spec(pkg_name)
|
||||
try:
|
||||
spec.update_variant_validate(variant_name, values)
|
||||
except (spack.variant.InvalidVariantValueError, KeyError, ValueError) as e:
|
||||
tty.debug(
|
||||
f"[SETUP]: rejected {str(variant)} as a preference for {pkg_name}: {str(e)}"
|
||||
)
|
||||
continue
|
||||
|
||||
for value in values:
|
||||
self.variant_values_from_specs.add((pkg_name, variant.name, value))
|
||||
|
|
|
@ -504,3 +504,13 @@ def test_sticky_variant_accounts_for_packages_yaml(self):
|
|||
with spack.config.override("packages:sticky-variant", {"variants": "+allow-gcc"}):
|
||||
s = Spec("sticky-variant %gcc").concretized()
|
||||
assert s.satisfies("%gcc") and s.satisfies("+allow-gcc")
|
||||
|
||||
@pytest.mark.regression("41134")
|
||||
@pytest.mark.only_clingo("Not backporting the fix to the old concretizer")
|
||||
def test_default_preference_variant_different_type_does_not_error(self):
|
||||
"""Tests that a different type for an existing variant in the 'all:' section of
|
||||
packages.yaml doesn't fail with an error.
|
||||
"""
|
||||
with spack.config.override("packages:all", {"variants": "+foo"}):
|
||||
s = Spec("a").concretized()
|
||||
assert s.satisfies("foo=bar")
|
||||
|
|
Loading…
Reference in a new issue