traverse: w/o deptype (#42345)
Add the empty deptype `spack.deptypes.NONE`. Test the case `traverse_nodes(deptype=spack.deptypes.NONE)` to not traverse dependencies, only de-duplicate. Use the construct in environment views that otherwise would branch on whether deps are enabled or not.
This commit is contained in:
parent
62ed5ee318
commit
890ec8d71c
3 changed files with 25 additions and 14 deletions
|
@ -36,6 +36,9 @@
|
|||
#: Default dependency type if none is specified
|
||||
DEFAULT: DepFlag = BUILD | LINK
|
||||
|
||||
#: A flag with no dependency types set
|
||||
NONE: DepFlag = 0
|
||||
|
||||
#: An iterator of all flag components
|
||||
ALL_FLAGS: Tuple[DepFlag, DepFlag, DepFlag, DepFlag] = (BUILD, LINK, RUN, TEST)
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
import llnl.util.filesystem as fs
|
||||
import llnl.util.tty as tty
|
||||
import llnl.util.tty.color as clr
|
||||
from llnl.util.lang import dedupe
|
||||
from llnl.util.link_tree import ConflictingSpecsError
|
||||
from llnl.util.symlink import symlink
|
||||
|
||||
|
@ -663,27 +662,23 @@ def __contains__(self, spec):
|
|||
|
||||
return True
|
||||
|
||||
def specs_for_view(self, concretized_root_specs):
|
||||
def specs_for_view(self, concrete_roots: List[Spec]) -> List[Spec]:
|
||||
"""
|
||||
From the list of concretized user specs in the environment, flatten
|
||||
the dags, and filter selected, installed specs, remove duplicates on dag hash.
|
||||
"""
|
||||
# With deps, requires traversal
|
||||
if self.link == "all" or self.link == "run":
|
||||
deptype = ("run") if self.link == "run" else ("link", "run")
|
||||
specs = list(
|
||||
traverse.traverse_nodes(
|
||||
concretized_root_specs, deptype=deptype, key=traverse.by_dag_hash
|
||||
)
|
||||
)
|
||||
if self.link == "all":
|
||||
deptype = dt.LINK | dt.RUN
|
||||
elif self.link == "run":
|
||||
deptype = dt.RUN
|
||||
else:
|
||||
specs = list(dedupe(concretized_root_specs, key=traverse.by_dag_hash))
|
||||
deptype = dt.NONE
|
||||
|
||||
specs = traverse.traverse_nodes(concrete_roots, deptype=deptype, key=traverse.by_dag_hash)
|
||||
|
||||
# Filter selected, installed specs
|
||||
with spack.store.STORE.db.read_transaction():
|
||||
specs = [s for s in specs if s in self and s.installed]
|
||||
|
||||
return specs
|
||||
return [s for s in specs if s in self and s.installed]
|
||||
|
||||
def regenerate(self, concretized_root_specs):
|
||||
specs = self.specs_for_view(concretized_root_specs)
|
||||
|
|
|
@ -395,3 +395,16 @@ def test_traverse_edges_topo(abstract_specs_toposort):
|
|||
out_edge_indices = [i for (i, (parent, child)) in enumerate(edges) if node == parent]
|
||||
if in_edge_indices and out_edge_indices:
|
||||
assert max(in_edge_indices) < min(out_edge_indices)
|
||||
|
||||
|
||||
def test_traverse_nodes_no_deps(abstract_specs_dtuse):
|
||||
"""Traversing nodes without deps should be the same as deduplicating the input specs. This may
|
||||
not look useful, but can be used to avoid a branch on the call site in which it's otherwise
|
||||
easy to forget to deduplicate input specs."""
|
||||
inputs = [
|
||||
abstract_specs_dtuse["dtuse"],
|
||||
abstract_specs_dtuse["dtlink5"],
|
||||
abstract_specs_dtuse["dtuse"], # <- duplicate
|
||||
]
|
||||
outputs = [x for x in traverse.traverse_nodes(inputs, deptype=dt.NONE)]
|
||||
assert outputs == [abstract_specs_dtuse["dtuse"], abstract_specs_dtuse["dtlink5"]]
|
||||
|
|
Loading…
Reference in a new issue