From b139cab687c9fcb1dc11b39f5bb2ec91b76c3dbc Mon Sep 17 00:00:00 2001 From: Greg Becker Date: Wed, 30 Nov 2022 23:25:57 -0800 Subject: conditional variant values: allow boolean (#33939) --- lib/spack/spack/solver/asp.py | 38 ++++++++++++++++------ lib/spack/spack/test/concretize.py | 18 ++++++---- .../conditional-values-in-variant/package.py | 7 ++++ 3 files changed, 46 insertions(+), 17 deletions(-) diff --git a/lib/spack/spack/solver/asp.py b/lib/spack/spack/solver/asp.py index 9ff88af4df..1a22cf5c6f 100644 --- a/lib/spack/spack/solver/asp.py +++ b/lib/spack/spack/solver/asp.py @@ -1017,17 +1017,35 @@ class SpackSolverSetup(object): values = [variant.default] for value in sorted(values): + if getattr(value, "when", True) is not True: # when=True means unconditional + condition_spec = spack.spec.Spec("{0}={1}".format(name, value)) + if value.when is False: + # This value is a conflict + # Cannot just prevent listing it as a possible value because it could + # also come in as a possible value from the command line + trigger_id = self.condition( + condition_spec, + name=pkg.name, + msg="invalid variant value {0}={1}".format(name, value), + ) + constraint_id = self.condition( + spack.spec.Spec(), + name=pkg.name, + msg="empty (total) conflict constraint", + ) + msg = "variant {0}={1} is conditionally disabled".format(name, value) + self.gen.fact(fn.conflict(pkg.name, trigger_id, constraint_id, msg)) + else: + imposed = spack.spec.Spec(value.when) + imposed.name = pkg.name + + self.condition( + required_spec=condition_spec, + imposed_spec=imposed, + name=pkg.name, + msg="%s variant %s value %s when %s" % (pkg.name, name, value, when), + ) self.gen.fact(fn.variant_possible_value(pkg.name, name, value)) - if hasattr(value, "when"): - required = spack.spec.Spec("{0}={1}".format(name, value)) - imposed = spack.spec.Spec(value.when) - imposed.name = pkg.name - self.condition( - required_spec=required, - imposed_spec=imposed, - name=pkg.name, - msg="%s variant %s value %s when %s" % (pkg.name, name, value, when), - ) if variant.sticky: self.gen.fact(fn.variant_sticky(pkg.name, name)) diff --git a/lib/spack/spack/test/concretize.py b/lib/spack/spack/test/concretize.py index 9afbf8f45b..55ad6a1b20 100644 --- a/lib/spack/spack/test/concretize.py +++ b/lib/spack/spack/test/concretize.py @@ -1481,21 +1481,25 @@ class TestConcretize(object): assert ver("2.7.21") == Spec("python@2.7.21").concretized().version @pytest.mark.parametrize( - "spec_str", + "spec_str,valid", [ - "conditional-values-in-variant@1.62.0 cxxstd=17", - "conditional-values-in-variant@1.62.0 cxxstd=2a", - "conditional-values-in-variant@1.72.0 cxxstd=2a", + ("conditional-values-in-variant@1.62.0 cxxstd=17", False), + ("conditional-values-in-variant@1.62.0 cxxstd=2a", False), + ("conditional-values-in-variant@1.72.0 cxxstd=2a", False), # Ensure disjoint set of values work too - "conditional-values-in-variant@1.72.0 staging=flexpath", + ("conditional-values-in-variant@1.72.0 staging=flexpath", False), + # Ensure conditional values set False fail too + ("conditional-values-in-variant foo=bar", False), + ("conditional-values-in-variant foo=foo", True), ], ) - def test_conditional_values_in_variants(self, spec_str): + def test_conditional_values_in_variants(self, spec_str, valid): if spack.config.get("config:concretizer") == "original": pytest.skip("Original concretizer doesn't resolve conditional values in variants") s = Spec(spec_str) - with pytest.raises((RuntimeError, spack.error.UnsatisfiableSpecError)): + raises = pytest.raises((RuntimeError, spack.error.UnsatisfiableSpecError)) + with llnl.util.lang.nullcontext() if valid else raises: s.concretize() def test_conditional_values_in_conditional_variant(self): diff --git a/var/spack/repos/builtin.mock/packages/conditional-values-in-variant/package.py b/var/spack/repos/builtin.mock/packages/conditional-values-in-variant/package.py index 788141565d..3dedabe7b2 100644 --- a/var/spack/repos/builtin.mock/packages/conditional-values-in-variant/package.py +++ b/var/spack/repos/builtin.mock/packages/conditional-values-in-variant/package.py @@ -38,3 +38,10 @@ class ConditionalValuesInVariant(Package): values=any_combination_of(conditional("flexpath", "dataspaces", when="@1.73.0:")), description="Enable dataspaces and/or flexpath staging transports", ) + + variant( + "foo", + default="foo", + values=(conditional("foo", when=True), conditional("bar", when=False)), + description="Variant with default condition false", + ) -- cgit v1.2.3-60-g2f50