From 3b06347f654266d03d5b9f07e58f2345d8afde11 Mon Sep 17 00:00:00 2001 From: Harmen Stoppels Date: Mon, 4 Mar 2024 20:50:04 +0100 Subject: [PATCH] repo.py: cleanup packages_with_tags (#42980) --- lib/spack/spack/cmd/external.py | 7 ++++--- lib/spack/spack/cmd/test.py | 2 +- lib/spack/spack/repo.py | 29 +++++++++++------------------ lib/spack/spack/solver/asp.py | 3 +-- lib/spack/spack/solver/counter.py | 4 ++-- 5 files changed, 19 insertions(+), 26 deletions(-) diff --git a/lib/spack/spack/cmd/external.py b/lib/spack/spack/cmd/external.py index 29be54ba64..8b6e750932 100644 --- a/lib/spack/spack/cmd/external.py +++ b/lib/spack/spack/cmd/external.py @@ -18,6 +18,7 @@ import spack.cray_manifest as cray_manifest import spack.detection import spack.error +import spack.repo import spack.util.environment from spack.cmd.common import arguments @@ -152,9 +153,9 @@ def external_find(args): def packages_to_search_for( *, names: Optional[List[str]], tags: List[str], exclude: Optional[List[str]] ): - result = [] - for current_tag in tags: - result.extend(spack.repo.PATH.packages_with_tags(current_tag, full=True)) + result = list( + {pkg for tag in tags for pkg in spack.repo.PATH.packages_with_tags(tag, full=True)} + ) if names: # Match both fully qualified and unqualified diff --git a/lib/spack/spack/cmd/test.py b/lib/spack/spack/cmd/test.py index e84df8c74a..5aded576b0 100644 --- a/lib/spack/spack/cmd/test.py +++ b/lib/spack/spack/cmd/test.py @@ -228,7 +228,7 @@ def create_reporter(args, specs_to_test, test_suite): def test_list(args): """list installed packages with available tests""" - tagged = set(spack.repo.PATH.packages_with_tags(*args.tag)) if args.tag else set() + tagged = spack.repo.PATH.packages_with_tags(*args.tag) if args.tag else set() def has_test_and_tags(pkg_class): tests = spack.install_test.test_functions(pkg_class) diff --git a/lib/spack/spack/repo.py b/lib/spack/spack/repo.py index 307654d328..b5f7640baf 100644 --- a/lib/spack/spack/repo.py +++ b/lib/spack/spack/repo.py @@ -25,7 +25,7 @@ import traceback import types import uuid -from typing import Any, Dict, List, Tuple, Union +from typing import Any, Dict, List, Set, Tuple, Union import llnl.path import llnl.util.filesystem as fs @@ -746,19 +746,17 @@ def all_package_paths(self): for name in self.all_package_names(): yield self.package_path(name) - def packages_with_tags(self, *tags, full=False): - """Returns a list of packages matching any of the tags in input. + def packages_with_tags(self, *tags: str, full: bool = False) -> Set[str]: + """Returns a set of packages matching any of the tags in input. Args: full: if True the package names in the output are fully-qualified """ - r = set() - for repo in self.repos: - current = repo.packages_with_tags(*tags) - if full: - current = [f"{repo.namespace}.{x}" for x in current] - r |= set(current) - return sorted(r) + return { + f"{repo.namespace}.{pkg}" if full else pkg + for repo in self.repos + for pkg in repo.packages_with_tags(*tags) + } def all_package_classes(self): for name in self.all_package_names(): @@ -1169,15 +1167,10 @@ def all_package_paths(self): for name in self.all_package_names(): yield self.package_path(name) - def packages_with_tags(self, *tags): + def packages_with_tags(self, *tags: str) -> Set[str]: v = set(self.all_package_names()) - index = self.tag_index - - for t in tags: - t = t.lower() - v &= set(index[t]) - - return sorted(v) + v.intersection_update(*(self.tag_index[tag.lower()] for tag in tags)) + return v def all_package_classes(self): """Iterator over all package *classes* in the repository. diff --git a/lib/spack/spack/solver/asp.py b/lib/spack/spack/solver/asp.py index 18c7dd371c..8137daea63 100644 --- a/lib/spack/spack/solver/asp.py +++ b/lib/spack/spack/solver/asp.py @@ -2287,8 +2287,7 @@ def setup( self.possible_virtuals = node_counter.possible_virtuals() self.pkgs = node_counter.possible_dependencies() - runtimes = spack.repo.PATH.packages_with_tags("runtime") - self.pkgs.update(set(runtimes)) + self.pkgs.update(spack.repo.PATH.packages_with_tags("runtime")) # Fail if we already know an unreachable node is requested for spec in specs: diff --git a/lib/spack/spack/solver/counter.py b/lib/spack/spack/solver/counter.py index 632740da05..72bff5f5bf 100644 --- a/lib/spack/spack/solver/counter.py +++ b/lib/spack/spack/solver/counter.py @@ -117,7 +117,7 @@ def _compute_cache_values(self): self._possible_dependencies = set(self._link_run) | set(self._total_build) def possible_packages_facts(self, gen, fn): - build_tools = set(spack.repo.PATH.packages_with_tags("build-tools")) + build_tools = spack.repo.PATH.packages_with_tags("build-tools") gen.h2("Packages with at most a single node") for package_name in sorted(self.possible_dependencies() - build_tools): gen.fact(fn.max_dupes(package_name, 1)) @@ -142,7 +142,7 @@ def possible_packages_facts(self, gen, fn): class FullDuplicatesCounter(MinimalDuplicatesCounter): def possible_packages_facts(self, gen, fn): - build_tools = set(spack.repo.PATH.packages_with_tags("build-tools")) + build_tools = spack.repo.PATH.packages_with_tags("build-tools") counter = collections.Counter( list(self._link_run) + list(self._total_build) + list(self._direct_build) )