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
|
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
|
#: Sanity checks on package directives
|
||||||
package_directives = AuditClass(
|
package_directives = AuditClass(
|
||||||
group="packages",
|
group="packages",
|
||||||
|
|
|
@ -1828,7 +1828,13 @@ def preferred_variants(self, pkg_name):
|
||||||
|
|
||||||
# perform validation of the variant and values
|
# perform validation of the variant and values
|
||||||
spec = spack.spec.Spec(pkg_name)
|
spec = spack.spec.Spec(pkg_name)
|
||||||
spec.update_variant_validate(variant_name, values)
|
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:
|
for value in values:
|
||||||
self.variant_values_from_specs.add((pkg_name, variant.name, value))
|
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"}):
|
with spack.config.override("packages:sticky-variant", {"variants": "+allow-gcc"}):
|
||||||
s = Spec("sticky-variant %gcc").concretized()
|
s = Spec("sticky-variant %gcc").concretized()
|
||||||
assert s.satisfies("%gcc") and s.satisfies("+allow-gcc")
|
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