conditional deps: tests for Spec.satisfies and Spec.constrain
Signed-off-by: Gregory Becker <becker33@llnl.gov>
This commit is contained in:
parent
0d021717ec
commit
a16d10edc9
@ -1817,7 +1817,9 @@ def _add_dependency(
|
|||||||
)
|
)
|
||||||
except StopIteration:
|
except StopIteration:
|
||||||
# Error if we have overlapping or incompatible deptypes
|
# Error if we have overlapping or incompatible deptypes
|
||||||
if any(not dt.compatible(dspec.depflag, depflag) for dspec in orig):
|
if any(not dt.compatible(dspec.depflag, depflag) for dspec in orig) and all(
|
||||||
|
dspec.when == when for dspec in orig
|
||||||
|
):
|
||||||
edge_attrs = f"deptypes={dt.flag_to_chars(depflag).strip()}"
|
edge_attrs = f"deptypes={dt.flag_to_chars(depflag).strip()}"
|
||||||
required_dep_str = f"^[{edge_attrs}] {str(spec)}"
|
required_dep_str = f"^[{edge_attrs}] {str(spec)}"
|
||||||
|
|
||||||
@ -3440,7 +3442,11 @@ def satisfies(self, other: Union[str, "Spec"], deps: bool = True) -> bool:
|
|||||||
mock_nodes_from_old_specfiles = set()
|
mock_nodes_from_old_specfiles = set()
|
||||||
for rhs_edge in other.traverse_edges(root=False, cover="edges"):
|
for rhs_edge in other.traverse_edges(root=False, cover="edges"):
|
||||||
# Skip checking any conditional edge that is not satisfied
|
# Skip checking any conditional edge that is not satisfied
|
||||||
if rhs_edge.when != Spec() and not rhs_edge.parent.satisfies(rhs_edge.when):
|
if (
|
||||||
|
rhs_edge.when != Spec()
|
||||||
|
and not rhs_edge.parent.satisfies(rhs_edge.when)
|
||||||
|
and not self.satisfies(rhs_edge.when)
|
||||||
|
):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# If we are checking for ^mpi we need to verify if there is any edge
|
# If we are checking for ^mpi we need to verify if there is any edge
|
||||||
@ -3527,13 +3533,17 @@ def satisfies(self, other: Union[str, "Spec"], deps: bool = True) -> bool:
|
|||||||
for rhs in other.traverse(root=False):
|
for rhs in other.traverse(root=False):
|
||||||
# Possible lhs nodes to match this rhs node
|
# Possible lhs nodes to match this rhs node
|
||||||
lhss = [lhs for lhs in lhs_nodes if lhs.satisfies(rhs, deps=False)]
|
lhss = [lhs for lhs in lhs_nodes if lhs.satisfies(rhs, deps=False)]
|
||||||
|
lhs_parents = [
|
||||||
|
lhs
|
||||||
|
for lhs in lhs_nodes
|
||||||
|
if any(lhs.satisfies(parent, deps=False) for parent in rhs.dependents())
|
||||||
|
]
|
||||||
|
|
||||||
# Check whether the node needs matching (not a conditional that isn't satisfied)
|
# Check whether the node needs matching (not a conditional that isn't satisfied)
|
||||||
in_edges = [
|
in_edges = [
|
||||||
e
|
e
|
||||||
for e in rhs.edges_from_dependents()
|
for e in rhs.edges_from_dependents()
|
||||||
if e.parent.satisfies(e.when)
|
if e.parent.satisfies(e.when) or any(lhp.satisfies(e.when) for lhp in lhs_parents)
|
||||||
or (lhss and all(lhs.satisfies(e.when) for lhs in lhss))
|
|
||||||
]
|
]
|
||||||
if not in_edges:
|
if not in_edges:
|
||||||
continue
|
continue
|
||||||
@ -3676,6 +3686,7 @@ def spid(spec):
|
|||||||
depflag=edge.depflag,
|
depflag=edge.depflag,
|
||||||
virtuals=edge.virtuals,
|
virtuals=edge.virtuals,
|
||||||
direct=edge.direct,
|
direct=edge.direct,
|
||||||
|
when=edge.when,
|
||||||
)
|
)
|
||||||
|
|
||||||
def copy(self, deps: Union[bool, dt.DepTypes, dt.DepFlag] = True, **kwargs):
|
def copy(self, deps: Union[bool, dt.DepTypes, dt.DepFlag] = True, **kwargs):
|
||||||
|
@ -327,6 +327,26 @@ class TestSpecSemantics:
|
|||||||
"ba5e334fe247335f3a116decfb5284100791dc302b5571ff5e664d8f9a6806c2"
|
"ba5e334fe247335f3a116decfb5284100791dc302b5571ff5e664d8f9a6806c2"
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
"libelf",
|
||||||
|
"%[when='^c' virtuals=c]gcc ^[when='+mpi' virtuals=mpi]mpich",
|
||||||
|
"libelf %[when='^c' virtuals=c]gcc ^[when='+mpi' virtuals=mpi]mpich",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"libelf %[when='^c' virtuals=c]gcc",
|
||||||
|
"%[when='^c' virtuals=c]gcc@10.3.1",
|
||||||
|
"libelf%[when='^c' virtuals=c]gcc@10.3.1",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"libelf %[when='^c' virtuals=c]gcc",
|
||||||
|
"%[when='^c' virtuals=c]gcc@10.3.1 ^[when='+mpi'] mpich",
|
||||||
|
"libelf%[when='^c' virtuals=c]gcc@10.3.1 ^[when='+mpi']mpich",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"libelf %[when='^c' virtuals=c]gcc",
|
||||||
|
"%[when='^cxx' virtuals=cxx]gcc@10.3.1",
|
||||||
|
"libelf%[when='^c' virtuals=c]gcc %[when='^cxx' virtuals=cxx]gcc@10.3.1",
|
||||||
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_abstract_specs_can_constrain_each_other(self, lhs, rhs, expected):
|
def test_abstract_specs_can_constrain_each_other(self, lhs, rhs, expected):
|
||||||
@ -573,6 +593,14 @@ def test_abstract_specs_with_propagation(self, lhs, rhs, expected, constrained):
|
|||||||
c.constrain(lhs)
|
c.constrain(lhs)
|
||||||
assert c == constrained
|
assert c == constrained
|
||||||
|
|
||||||
|
def test_satisfies_conditional_dep(self):
|
||||||
|
concrete = spack.concretize.concretize_one("mpileaks^mpich")
|
||||||
|
assert concrete.satisfies("^[when='^mpi' virtuals=mpi]mpich")
|
||||||
|
assert concrete.satisfies("^[when='^notapackage']zmpi")
|
||||||
|
assert not concrete.satisfies("^[virtuals=blas]mpich")
|
||||||
|
assert not concrete.satisfies("^[when='^mpi' virtuals=blas]mpich")
|
||||||
|
assert not concrete.satisfies("^[when='^mpi']zmpi")
|
||||||
|
|
||||||
def test_satisfies_single_valued_variant(self):
|
def test_satisfies_single_valued_variant(self):
|
||||||
"""Tests that the case reported in
|
"""Tests that the case reported in
|
||||||
https://github.com/spack/spack/pull/2386#issuecomment-282147639
|
https://github.com/spack/spack/pull/2386#issuecomment-282147639
|
||||||
|
Loading…
Reference in New Issue
Block a user