Rework spack.database.InstallStatuses into a flag (#47321)

This commit is contained in:
Massimiliano Culpo 2024-11-14 15:43:31 +01:00 committed by GitHub
parent c0196cde39
commit fb46c7a72d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 194 additions and 157 deletions

View File

@ -87,6 +87,8 @@
from spack.stage import Stage from spack.stage import Stage
from spack.util.executable import which from spack.util.executable import which
from .enums import InstallRecordStatus
BUILD_CACHE_RELATIVE_PATH = "build_cache" BUILD_CACHE_RELATIVE_PATH = "build_cache"
BUILD_CACHE_KEYS_RELATIVE_PATH = "_pgp" BUILD_CACHE_KEYS_RELATIVE_PATH = "_pgp"
@ -252,7 +254,7 @@ def _associate_built_specs_with_mirror(self, cache_key, mirror_url):
spec_list = [ spec_list = [
s s
for s in db.query_local(installed=any) for s in db.query_local(installed=InstallRecordStatus.ANY)
if s.external or db.query_local_by_spec_hash(s.dag_hash()).in_buildcache if s.external or db.query_local_by_spec_hash(s.dag_hash()).in_buildcache
] ]

View File

@ -9,7 +9,7 @@
import re import re
import sys import sys
from collections import Counter from collections import Counter
from typing import List, Union from typing import List, Optional, Union
import llnl.string import llnl.string
import llnl.util.tty as tty import llnl.util.tty as tty
@ -33,6 +33,8 @@
import spack.util.spack_json as sjson import spack.util.spack_json as sjson
import spack.util.spack_yaml as syaml import spack.util.spack_yaml as syaml
from ..enums import InstallRecordStatus
# cmd has a submodule called "list" so preserve the python list module # cmd has a submodule called "list" so preserve the python list module
python_list = list python_list = list
@ -267,39 +269,48 @@ def matching_specs_from_env(specs):
return _concretize_spec_pairs(spec_pairs + additional_concrete_specs)[: len(spec_pairs)] return _concretize_spec_pairs(spec_pairs + additional_concrete_specs)[: len(spec_pairs)]
def disambiguate_spec(spec, env, local=False, installed=True, first=False): def disambiguate_spec(
spec: spack.spec.Spec,
env: Optional[ev.Environment],
local: bool = False,
installed: Union[bool, InstallRecordStatus] = True,
first: bool = False,
) -> spack.spec.Spec:
"""Given a spec, figure out which installed package it refers to. """Given a spec, figure out which installed package it refers to.
Arguments: Args:
spec (spack.spec.Spec): a spec to disambiguate spec: a spec to disambiguate
env (spack.environment.Environment): a spack environment, env: a spack environment, if one is active, or None if no environment is active
if one is active, or None if no environment is active local: do not search chained spack instances
local (bool): do not search chained spack instances installed: install status argument passed to database query.
installed (bool or spack.database.InstallStatus or typing.Iterable): first: returns the first matching spec, even if more than one match is found
install status argument passed to database query.
See ``spack.database.Database._query`` for details.
""" """
hashes = env.all_hashes() if env else None hashes = env.all_hashes() if env else None
return disambiguate_spec_from_hashes(spec, hashes, local, installed, first) return disambiguate_spec_from_hashes(spec, hashes, local, installed, first)
def disambiguate_spec_from_hashes(spec, hashes, local=False, installed=True, first=False): def disambiguate_spec_from_hashes(
spec: spack.spec.Spec,
hashes: List[str],
local: bool = False,
installed: Union[bool, InstallRecordStatus] = True,
first: bool = False,
) -> spack.spec.Spec:
"""Given a spec and a list of hashes, get concrete spec the spec refers to. """Given a spec and a list of hashes, get concrete spec the spec refers to.
Arguments: Arguments:
spec (spack.spec.Spec): a spec to disambiguate spec: a spec to disambiguate
hashes (typing.Iterable): a set of hashes of specs among which to disambiguate hashes: a set of hashes of specs among which to disambiguate
local (bool): do not search chained spack instances local: if True, do not search chained spack instances
installed (bool or spack.database.InstallStatus or typing.Iterable): installed: install status argument passed to database query.
install status argument passed to database query. first: returns the first matching spec, even if more than one match is found
See ``spack.database.Database._query`` for details.
""" """
if local: if local:
matching_specs = spack.store.STORE.db.query_local(spec, hashes=hashes, installed=installed) matching_specs = spack.store.STORE.db.query_local(spec, hashes=hashes, installed=installed)
else: else:
matching_specs = spack.store.STORE.db.query(spec, hashes=hashes, installed=installed) matching_specs = spack.store.STORE.db.query(spec, hashes=hashes, installed=installed)
if not matching_specs: if not matching_specs:
tty.die("Spec '%s' matches no installed packages." % spec) tty.die(f"Spec '{spec}' matches no installed packages.")
elif first: elif first:
return matching_specs[0] return matching_specs[0]

View File

@ -34,6 +34,8 @@
from spack.cmd.common import arguments from spack.cmd.common import arguments
from spack.spec import Spec, save_dependency_specfiles from spack.spec import Spec, save_dependency_specfiles
from ..enums import InstallRecordStatus
description = "create, download and install binary packages" description = "create, download and install binary packages"
section = "packaging" section = "packaging"
level = "long" level = "long"
@ -308,7 +310,10 @@ def setup_parser(subparser: argparse.ArgumentParser):
def _matching_specs(specs: List[Spec]) -> List[Spec]: def _matching_specs(specs: List[Spec]) -> List[Spec]:
"""Disambiguate specs and return a list of matching specs""" """Disambiguate specs and return a list of matching specs"""
return [spack.cmd.disambiguate_spec(s, ev.active_environment(), installed=any) for s in specs] return [
spack.cmd.disambiguate_spec(s, ev.active_environment(), installed=InstallRecordStatus.ANY)
for s in specs
]
def _format_spec(spec: Spec) -> str: def _format_spec(spec: Spec) -> str:

View File

@ -23,9 +23,10 @@
import spack.installer import spack.installer
import spack.store import spack.store
from spack.cmd.common import arguments from spack.cmd.common import arguments
from spack.database import InstallStatuses
from spack.error import SpackError from spack.error import SpackError
from ..enums import InstallRecordStatus
description = "replace one package with another via symlinks" description = "replace one package with another via symlinks"
section = "admin" section = "admin"
level = "long" level = "long"
@ -95,8 +96,12 @@ def deprecate(parser, args):
if len(specs) != 2: if len(specs) != 2:
raise SpackError("spack deprecate requires exactly two specs") raise SpackError("spack deprecate requires exactly two specs")
install_query = [InstallStatuses.INSTALLED, InstallStatuses.DEPRECATED] deprecate = spack.cmd.disambiguate_spec(
deprecate = spack.cmd.disambiguate_spec(specs[0], env, local=True, installed=install_query) specs[0],
env,
local=True,
installed=(InstallRecordStatus.INSTALLED | InstallRecordStatus.DEPRECATED),
)
if args.install: if args.install:
deprecator = specs[1].concretized() deprecator = specs[1].concretized()

View File

@ -17,7 +17,8 @@
import spack.spec import spack.spec
import spack.store import spack.store
from spack.cmd.common import arguments from spack.cmd.common import arguments
from spack.database import InstallStatuses
from ..enums import InstallRecordStatus
description = "list and search installed packages" description = "list and search installed packages"
section = "basic" section = "basic"
@ -137,21 +138,22 @@ def setup_parser(subparser):
subparser.add_argument( subparser.add_argument(
"--loaded", action="store_true", help="show only packages loaded in the user environment" "--loaded", action="store_true", help="show only packages loaded in the user environment"
) )
subparser.add_argument( only_missing_or_deprecated = subparser.add_mutually_exclusive_group()
only_missing_or_deprecated.add_argument(
"-M", "-M",
"--only-missing", "--only-missing",
action="store_true", action="store_true",
dest="only_missing", dest="only_missing",
help="show only missing dependencies", help="show only missing dependencies",
) )
only_missing_or_deprecated.add_argument(
"--only-deprecated", action="store_true", help="show only deprecated packages"
)
subparser.add_argument( subparser.add_argument(
"--deprecated", "--deprecated",
action="store_true", action="store_true",
help="show deprecated packages as well as installed specs", help="show deprecated packages as well as installed specs",
) )
subparser.add_argument(
"--only-deprecated", action="store_true", help="show only deprecated packages"
)
subparser.add_argument( subparser.add_argument(
"--install-tree", "--install-tree",
action="store", action="store",
@ -165,14 +167,23 @@ def setup_parser(subparser):
def query_arguments(args): def query_arguments(args):
# Set up query arguments. if args.only_missing and (args.deprecated or args.missing):
installed = [] raise RuntimeError("cannot use --only-missing with --deprecated, or --missing")
if not (args.only_missing or args.only_deprecated):
installed.append(InstallStatuses.INSTALLED) if args.only_deprecated and (args.deprecated or args.missing):
if (args.deprecated or args.only_deprecated) and not args.only_missing: raise RuntimeError("cannot use --only-deprecated with --deprecated, or --missing")
installed.append(InstallStatuses.DEPRECATED)
if (args.missing or args.only_missing) and not args.only_deprecated: installed = InstallRecordStatus.INSTALLED
installed.append(InstallStatuses.MISSING) if args.only_missing:
installed = InstallRecordStatus.MISSING
elif args.only_deprecated:
installed = InstallRecordStatus.DEPRECATED
if args.missing:
installed |= InstallRecordStatus.MISSING
if args.deprecated:
installed |= InstallRecordStatus.DEPRECATED
predicate_fn = None predicate_fn = None
if args.unknown: if args.unknown:

View File

@ -10,7 +10,8 @@
import spack.cmd import spack.cmd
import spack.store import spack.store
from spack.cmd.common import arguments from spack.cmd.common import arguments
from spack.database import InstallStatuses
from ..enums import InstallRecordStatus
description = "mark packages as explicitly or implicitly installed" description = "mark packages as explicitly or implicitly installed"
section = "admin" section = "admin"
@ -67,8 +68,7 @@ def find_matching_specs(specs, allow_multiple_matches=False):
has_errors = False has_errors = False
for spec in specs: for spec in specs:
install_query = [InstallStatuses.INSTALLED] matching = spack.store.STORE.db.query_local(spec, installed=InstallRecordStatus.INSTALLED)
matching = spack.store.STORE.db.query_local(spec, installed=install_query)
# For each spec provided, make sure it refers to only one package. # For each spec provided, make sure it refers to only one package.
# Fail and ask user to be unambiguous if it doesn't # Fail and ask user to be unambiguous if it doesn't
if not allow_multiple_matches and len(matching) > 1: if not allow_multiple_matches and len(matching) > 1:

View File

@ -17,7 +17,8 @@
import spack.store import spack.store
import spack.traverse as traverse import spack.traverse as traverse
from spack.cmd.common import arguments from spack.cmd.common import arguments
from spack.database import InstallStatuses
from ..enums import InstallRecordStatus
description = "remove installed packages" description = "remove installed packages"
section = "build" section = "build"
@ -99,12 +100,14 @@ def find_matching_specs(
hashes = env.all_hashes() if env else None hashes = env.all_hashes() if env else None
# List of specs that match expressions given via command line # List of specs that match expressions given via command line
specs_from_cli: List["spack.spec.Spec"] = [] specs_from_cli: List[spack.spec.Spec] = []
has_errors = False has_errors = False
for spec in specs: for spec in specs:
install_query = [InstallStatuses.INSTALLED, InstallStatuses.DEPRECATED]
matching = spack.store.STORE.db.query_local( matching = spack.store.STORE.db.query_local(
spec, hashes=hashes, installed=install_query, origin=origin spec,
hashes=hashes,
installed=(InstallRecordStatus.INSTALLED | InstallRecordStatus.DEPRECATED),
origin=origin,
) )
# For each spec provided, make sure it refers to only one package. # For each spec provided, make sure it refers to only one package.
# Fail and ask user to be unambiguous if it doesn't # Fail and ask user to be unambiguous if it doesn't

View File

@ -69,6 +69,8 @@
from spack.error import SpackError from spack.error import SpackError
from spack.util.crypto import bit_length from spack.util.crypto import bit_length
from .enums import InstallRecordStatus
# TODO: Provide an API automatically retyring a build after detecting and # TODO: Provide an API automatically retyring a build after detecting and
# TODO: clearing a failure. # TODO: clearing a failure.
@ -160,36 +162,12 @@ def converter(self, spec_like, *args, **kwargs):
return converter return converter
class InstallStatus(str): def normalize_query(installed: Union[bool, InstallRecordStatus]) -> InstallRecordStatus:
pass if installed is True:
installed = InstallRecordStatus.INSTALLED
elif installed is False:
class InstallStatuses: installed = InstallRecordStatus.MISSING
INSTALLED = InstallStatus("installed") return installed
DEPRECATED = InstallStatus("deprecated")
MISSING = InstallStatus("missing")
@classmethod
def canonicalize(cls, query_arg):
if query_arg is True:
return [cls.INSTALLED]
if query_arg is False:
return [cls.MISSING]
if query_arg is any:
return [cls.INSTALLED, cls.DEPRECATED, cls.MISSING]
if isinstance(query_arg, InstallStatus):
return [query_arg]
try:
statuses = list(query_arg)
if all(isinstance(x, InstallStatus) for x in statuses):
return statuses
except TypeError:
pass
raise TypeError(
"installation query must be `any`, boolean, "
"InstallStatus, or iterable of InstallStatus"
)
class InstallRecord: class InstallRecord:
@ -227,8 +205,8 @@ def __init__(
installation_time: Optional[float] = None, installation_time: Optional[float] = None,
deprecated_for: Optional[str] = None, deprecated_for: Optional[str] = None,
in_buildcache: bool = False, in_buildcache: bool = False,
origin=None, origin: Optional[str] = None,
): ) -> None:
self.spec = spec self.spec = spec
self.path = str(path) if path else None self.path = str(path) if path else None
self.installed = bool(installed) self.installed = bool(installed)
@ -239,14 +217,12 @@ def __init__(
self.in_buildcache = in_buildcache self.in_buildcache = in_buildcache
self.origin = origin self.origin = origin
def install_type_matches(self, installed): def install_type_matches(self, installed: InstallRecordStatus) -> bool:
installed = InstallStatuses.canonicalize(installed)
if self.installed: if self.installed:
return InstallStatuses.INSTALLED in installed return InstallRecordStatus.INSTALLED in installed
elif self.deprecated_for: elif self.deprecated_for:
return InstallStatuses.DEPRECATED in installed return InstallRecordStatus.DEPRECATED in installed
else: return InstallRecordStatus.MISSING in installed
return InstallStatuses.MISSING in installed
def to_dict(self, include_fields=DEFAULT_INSTALL_RECORD_FIELDS): def to_dict(self, include_fields=DEFAULT_INSTALL_RECORD_FIELDS):
rec_dict = {} rec_dict = {}
@ -1396,7 +1372,13 @@ def installed_extensions_for(self, extendee_spec: "spack.spec.Spec"):
if spec.package.extends(extendee_spec): if spec.package.extends(extendee_spec):
yield spec.package yield spec.package
def _get_by_hash_local(self, dag_hash, default=None, installed=any): def _get_by_hash_local(
self,
dag_hash: str,
default: Optional[List["spack.spec.Spec"]] = None,
installed: Union[bool, InstallRecordStatus] = InstallRecordStatus.ANY,
) -> Optional[List["spack.spec.Spec"]]:
installed = normalize_query(installed)
# hash is a full hash and is in the data somewhere # hash is a full hash and is in the data somewhere
if dag_hash in self._data: if dag_hash in self._data:
rec = self._data[dag_hash] rec = self._data[dag_hash]
@ -1405,8 +1387,7 @@ def _get_by_hash_local(self, dag_hash, default=None, installed=any):
else: else:
return default return default
# check if hash is a prefix of some installed (or previously # check if hash is a prefix of some installed (or previously installed) spec.
# installed) spec.
matches = [ matches = [
record.spec record.spec
for h, record in self._data.items() for h, record in self._data.items()
@ -1418,52 +1399,43 @@ def _get_by_hash_local(self, dag_hash, default=None, installed=any):
# nothing found # nothing found
return default return default
def get_by_hash_local(self, dag_hash, default=None, installed=any): def get_by_hash_local(
self,
dag_hash: str,
default: Optional[List["spack.spec.Spec"]] = None,
installed: Union[bool, InstallRecordStatus] = InstallRecordStatus.ANY,
) -> Optional[List["spack.spec.Spec"]]:
"""Look up a spec in *this DB* by DAG hash, or by a DAG hash prefix. """Look up a spec in *this DB* by DAG hash, or by a DAG hash prefix.
Arguments: Args:
dag_hash (str): hash (or hash prefix) to look up dag_hash: hash (or hash prefix) to look up
default (object or None): default value to return if dag_hash is default: default value to return if dag_hash is not in the DB
not in the DB (default: None) installed: if ``True``, includes only installed specs in the search; if ``False``
installed (bool or InstallStatus or typing.Iterable or None): only missing specs. Otherwise, a InstallRecordStatus flag.
if ``True``, includes only installed
specs in the search; if ``False`` only missing specs, and if
``any``, all specs in database. If an InstallStatus or iterable
of InstallStatus, returns specs whose install status
(installed, deprecated, or missing) matches (one of) the
InstallStatus. (default: any)
``installed`` defaults to ``any`` so that we can refer to any ``installed`` defaults to ``InstallRecordStatus.ANY`` so we can refer to any known hash.
known hash. Note that ``query()`` and ``query_one()`` differ in
that they only return installed specs by default.
Returns:
(list): a list of specs matching the hash or hash prefix
``query()`` and ``query_one()`` differ in that they only return installed specs by default.
""" """
with self.read_transaction(): with self.read_transaction():
return self._get_by_hash_local(dag_hash, default=default, installed=installed) return self._get_by_hash_local(dag_hash, default=default, installed=installed)
def get_by_hash(self, dag_hash, default=None, installed=any): def get_by_hash(
self,
dag_hash: str,
default: Optional[List["spack.spec.Spec"]] = None,
installed: Union[bool, InstallRecordStatus] = InstallRecordStatus.ANY,
) -> Optional[List["spack.spec.Spec"]]:
"""Look up a spec by DAG hash, or by a DAG hash prefix. """Look up a spec by DAG hash, or by a DAG hash prefix.
Arguments: Args:
dag_hash (str): hash (or hash prefix) to look up dag_hash: hash (or hash prefix) to look up
default (object or None): default value to return if dag_hash is default: default value to return if dag_hash is not in the DB
not in the DB (default: None) installed: if ``True``, includes only installed specs in the search; if ``False``
installed (bool or InstallStatus or typing.Iterable or None): only missing specs. Otherwise, a InstallRecordStatus flag.
if ``True``, includes only installed specs in the search; if ``False``
only missing specs, and if ``any``, all specs in database. If an
InstallStatus or iterable of InstallStatus, returns specs whose install
status (installed, deprecated, or missing) matches (one of) the
InstallStatus. (default: any)
``installed`` defaults to ``any`` so that we can refer to any ``installed`` defaults to ``InstallRecordStatus.ANY`` so we can refer to any known hash.
known hash. Note that ``query()`` and ``query_one()`` differ in ``query()`` and ``query_one()`` differ in that they only return installed specs by default.
that they only return installed specs by default.
Returns:
(list): a list of specs matching the hash or hash prefix
""" """
@ -1483,7 +1455,7 @@ def _query(
query_spec: Optional[Union[str, "spack.spec.Spec"]] = None, query_spec: Optional[Union[str, "spack.spec.Spec"]] = None,
*, *,
predicate_fn: Optional[SelectType] = None, predicate_fn: Optional[SelectType] = None,
installed: Union[bool, InstallStatus, List[InstallStatus]] = True, installed: Union[bool, InstallRecordStatus] = True,
explicit: Optional[bool] = None, explicit: Optional[bool] = None,
start_date: Optional[datetime.datetime] = None, start_date: Optional[datetime.datetime] = None,
end_date: Optional[datetime.datetime] = None, end_date: Optional[datetime.datetime] = None,
@ -1491,6 +1463,7 @@ def _query(
in_buildcache: Optional[bool] = None, in_buildcache: Optional[bool] = None,
origin: Optional[str] = None, origin: Optional[str] = None,
) -> List["spack.spec.Spec"]: ) -> List["spack.spec.Spec"]:
installed = normalize_query(installed)
# Restrict the set of records over which we iterate first # Restrict the set of records over which we iterate first
matching_hashes = self._data matching_hashes = self._data
@ -1560,7 +1533,7 @@ def query_local(
query_spec: Optional[Union[str, "spack.spec.Spec"]] = None, query_spec: Optional[Union[str, "spack.spec.Spec"]] = None,
*, *,
predicate_fn: Optional[SelectType] = None, predicate_fn: Optional[SelectType] = None,
installed: Union[bool, InstallStatus, List[InstallStatus]] = True, installed: Union[bool, InstallRecordStatus] = True,
explicit: Optional[bool] = None, explicit: Optional[bool] = None,
start_date: Optional[datetime.datetime] = None, start_date: Optional[datetime.datetime] = None,
end_date: Optional[datetime.datetime] = None, end_date: Optional[datetime.datetime] = None,
@ -1620,7 +1593,7 @@ def query(
query_spec: Optional[Union[str, "spack.spec.Spec"]] = None, query_spec: Optional[Union[str, "spack.spec.Spec"]] = None,
*, *,
predicate_fn: Optional[SelectType] = None, predicate_fn: Optional[SelectType] = None,
installed: Union[bool, InstallStatus, List[InstallStatus]] = True, installed: Union[bool, InstallRecordStatus] = True,
explicit: Optional[bool] = None, explicit: Optional[bool] = None,
start_date: Optional[datetime.datetime] = None, start_date: Optional[datetime.datetime] = None,
end_date: Optional[datetime.datetime] = None, end_date: Optional[datetime.datetime] = None,
@ -1628,7 +1601,7 @@ def query(
hashes: Optional[List[str]] = None, hashes: Optional[List[str]] = None,
origin: Optional[str] = None, origin: Optional[str] = None,
install_tree: str = "all", install_tree: str = "all",
): ) -> List["spack.spec.Spec"]:
"""Queries the Spack database including all upstream databases. """Queries the Spack database including all upstream databases.
Args: Args:
@ -1709,13 +1682,14 @@ def query(
) )
results = list(local_results) + list(x for x in upstream_results if x not in local_results) results = list(local_results) + list(x for x in upstream_results if x not in local_results)
return sorted(results) results.sort()
return results
def query_one( def query_one(
self, self,
query_spec: Optional[Union[str, "spack.spec.Spec"]], query_spec: Optional[Union[str, "spack.spec.Spec"]],
predicate_fn: Optional[SelectType] = None, predicate_fn: Optional[SelectType] = None,
installed: Union[bool, InstallStatus, List[InstallStatus]] = True, installed: Union[bool, InstallRecordStatus] = True,
) -> Optional["spack.spec.Spec"]: ) -> Optional["spack.spec.Spec"]:
"""Query for exactly one spec that matches the query spec. """Query for exactly one spec that matches the query spec.

15
lib/spack/spack/enums.py Normal file
View File

@ -0,0 +1,15 @@
# Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
"""Enumerations used throughout Spack"""
import enum
class InstallRecordStatus(enum.Flag):
"""Enum flag to facilitate querying status from the DB"""
INSTALLED = enum.auto()
DEPRECATED = enum.auto()
MISSING = enum.auto()
ANY = INSTALLED | DEPRECATED | MISSING

View File

@ -95,6 +95,8 @@
import spack.version as vn import spack.version as vn
import spack.version.git_ref_lookup import spack.version.git_ref_lookup
from .enums import InstallRecordStatus
__all__ = [ __all__ = [
"CompilerSpec", "CompilerSpec",
"Spec", "Spec",
@ -2071,7 +2073,7 @@ def _lookup_hash(self):
# First env, then store, then binary cache # First env, then store, then binary cache
matches = ( matches = (
(active_env.all_matching_specs(self) if active_env else []) (active_env.all_matching_specs(self) if active_env else [])
or spack.store.STORE.db.query(self, installed=any) or spack.store.STORE.db.query(self, installed=InstallRecordStatus.ANY)
or spack.binary_distribution.BinaryCacheQuery(True)(self) or spack.binary_distribution.BinaryCacheQuery(True)(self)
) )

View File

@ -7,7 +7,7 @@
import spack.spec import spack.spec
import spack.store import spack.store
from spack.database import InstallStatuses from spack.enums import InstallRecordStatus
from spack.main import SpackCommand from spack.main import SpackCommand
install = SpackCommand("install") install = SpackCommand("install")
@ -26,7 +26,7 @@ def test_deprecate(mock_packages, mock_archive, mock_fetch, install_mockery):
deprecate("-y", "libelf@0.8.10", "libelf@0.8.13") deprecate("-y", "libelf@0.8.10", "libelf@0.8.13")
non_deprecated = spack.store.STORE.db.query() non_deprecated = spack.store.STORE.db.query()
all_available = spack.store.STORE.db.query(installed=any) all_available = spack.store.STORE.db.query(installed=InstallRecordStatus.ANY)
assert all_available == all_installed assert all_available == all_installed
assert non_deprecated == spack.store.STORE.db.query("libelf@0.8.13") assert non_deprecated == spack.store.STORE.db.query("libelf@0.8.13")
@ -56,7 +56,7 @@ def test_deprecate_install(mock_packages, mock_archive, mock_fetch, install_mock
deprecate("-y", "-i", "libelf@0.8.10", "libelf@0.8.13") deprecate("-y", "-i", "libelf@0.8.10", "libelf@0.8.13")
non_deprecated = spack.store.STORE.db.query() non_deprecated = spack.store.STORE.db.query()
deprecated = spack.store.STORE.db.query(installed=InstallStatuses.DEPRECATED) deprecated = spack.store.STORE.db.query(installed=InstallRecordStatus.DEPRECATED)
assert deprecated == to_deprecate assert deprecated == to_deprecate
assert len(non_deprecated) == 1 assert len(non_deprecated) == 1
assert non_deprecated[0].satisfies("libelf@0.8.13") assert non_deprecated[0].satisfies("libelf@0.8.13")
@ -75,8 +75,8 @@ def test_deprecate_deps(mock_packages, mock_archive, mock_fetch, install_mockery
deprecate("-y", "-d", "libdwarf@20130207", "libdwarf@20130729") deprecate("-y", "-d", "libdwarf@20130207", "libdwarf@20130729")
non_deprecated = spack.store.STORE.db.query() non_deprecated = spack.store.STORE.db.query()
all_available = spack.store.STORE.db.query(installed=any) all_available = spack.store.STORE.db.query(installed=InstallRecordStatus.ANY)
deprecated = spack.store.STORE.db.query(installed=InstallStatuses.DEPRECATED) deprecated = spack.store.STORE.db.query(installed=InstallRecordStatus.DEPRECATED)
assert all_available == all_installed assert all_available == all_installed
assert sorted(all_available) == sorted(deprecated + non_deprecated) assert sorted(all_available) == sorted(deprecated + non_deprecated)
@ -96,7 +96,9 @@ def test_uninstall_deprecated(mock_packages, mock_archive, mock_fetch, install_m
uninstall("-y", "libelf@0.8.10") uninstall("-y", "libelf@0.8.10")
assert spack.store.STORE.db.query() == spack.store.STORE.db.query(installed=any) assert spack.store.STORE.db.query() == spack.store.STORE.db.query(
installed=InstallRecordStatus.ANY
)
assert spack.store.STORE.db.query() == non_deprecated assert spack.store.STORE.db.query() == non_deprecated
@ -116,7 +118,7 @@ def test_deprecate_already_deprecated(mock_packages, mock_archive, mock_fetch, i
deprecate("-y", "libelf@0.8.10", "libelf@0.8.13") deprecate("-y", "libelf@0.8.10", "libelf@0.8.13")
non_deprecated = spack.store.STORE.db.query() non_deprecated = spack.store.STORE.db.query()
all_available = spack.store.STORE.db.query(installed=any) all_available = spack.store.STORE.db.query(installed=InstallRecordStatus.ANY)
assert len(non_deprecated) == 2 assert len(non_deprecated) == 2
assert len(all_available) == 3 assert len(all_available) == 3
@ -143,7 +145,7 @@ def test_deprecate_deprecator(mock_packages, mock_archive, mock_fetch, install_m
deprecate("-y", "libelf@0.8.12", "libelf@0.8.13") deprecate("-y", "libelf@0.8.12", "libelf@0.8.13")
non_deprecated = spack.store.STORE.db.query() non_deprecated = spack.store.STORE.db.query()
all_available = spack.store.STORE.db.query(installed=any) all_available = spack.store.STORE.db.query(installed=InstallRecordStatus.ANY)
assert len(non_deprecated) == 1 assert len(non_deprecated) == 1
assert len(all_available) == 3 assert len(all_available) == 3

View File

@ -17,6 +17,7 @@
import spack.repo import spack.repo
import spack.store import spack.store
import spack.user_environment as uenv import spack.user_environment as uenv
from spack.enums import InstallRecordStatus
from spack.main import SpackCommand from spack.main import SpackCommand
from spack.spec import Spec from spack.spec import Spec
from spack.test.conftest import create_test_repo from spack.test.conftest import create_test_repo
@ -75,7 +76,7 @@ def test_query_arguments():
assert "installed" in q_args assert "installed" in q_args
assert "predicate_fn" in q_args assert "predicate_fn" in q_args
assert "explicit" in q_args assert "explicit" in q_args
assert q_args["installed"] == ["installed"] assert q_args["installed"] == InstallRecordStatus.INSTALLED
assert q_args["predicate_fn"] is None assert q_args["predicate_fn"] is None
assert q_args["explicit"] is None assert q_args["explicit"] is None
assert "start_date" in q_args assert "start_date" in q_args

View File

@ -6,6 +6,7 @@
import spack.store import spack.store
from spack.database import Database from spack.database import Database
from spack.enums import InstallRecordStatus
from spack.main import SpackCommand from spack.main import SpackCommand
install = SpackCommand("install") install = SpackCommand("install")
@ -57,18 +58,18 @@ def test_reindex_with_deprecated_packages(
db = spack.store.STORE.db db = spack.store.STORE.db
all_installed = db.query(installed=any) all_installed = db.query(installed=InstallRecordStatus.ANY)
non_deprecated = db.query(installed=True) non_deprecated = db.query(installed=True)
_clear_db(tmp_path) _clear_db(tmp_path)
reindex() reindex()
assert db.query(installed=any) == all_installed assert db.query(installed=InstallRecordStatus.ANY) == all_installed
assert db.query(installed=True) == non_deprecated assert db.query(installed=True) == non_deprecated
old_libelf = db.query_local_by_spec_hash( old_libelf = db.query_local_by_spec_hash(
db.query_local("libelf@0.8.12", installed=any)[0].dag_hash() db.query_local("libelf@0.8.12", installed=InstallRecordStatus.ANY)[0].dag_hash()
) )
new_libelf = db.query_local_by_spec_hash( new_libelf = db.query_local_by_spec_hash(
db.query_local("libelf@0.8.13", installed=True)[0].dag_hash() db.query_local("libelf@0.8.13", installed=True)[0].dag_hash()

View File

@ -11,6 +11,7 @@
import spack.cmd.uninstall import spack.cmd.uninstall
import spack.environment import spack.environment
import spack.store import spack.store
from spack.enums import InstallRecordStatus
from spack.main import SpackCommand, SpackCommandError from spack.main import SpackCommand, SpackCommandError
uninstall = SpackCommand("uninstall") uninstall = SpackCommand("uninstall")
@ -129,10 +130,10 @@ def validate_callpath_spec(installed):
specs = spack.store.STORE.db.get_by_hash(dag_hash[:7], installed=installed) specs = spack.store.STORE.db.get_by_hash(dag_hash[:7], installed=installed)
assert len(specs) == 1 and specs[0] == callpath_spec assert len(specs) == 1 and specs[0] == callpath_spec
specs = spack.store.STORE.db.get_by_hash(dag_hash, installed=any) specs = spack.store.STORE.db.get_by_hash(dag_hash, installed=InstallRecordStatus.ANY)
assert len(specs) == 1 and specs[0] == callpath_spec assert len(specs) == 1 and specs[0] == callpath_spec
specs = spack.store.STORE.db.get_by_hash(dag_hash[:7], installed=any) specs = spack.store.STORE.db.get_by_hash(dag_hash[:7], installed=InstallRecordStatus.ANY)
assert len(specs) == 1 and specs[0] == callpath_spec assert len(specs) == 1 and specs[0] == callpath_spec
specs = spack.store.STORE.db.get_by_hash(dag_hash, installed=not installed) specs = spack.store.STORE.db.get_by_hash(dag_hash, installed=not installed)
@ -147,7 +148,7 @@ def validate_callpath_spec(installed):
spec = spack.store.STORE.db.query_one("callpath ^mpich", installed=installed) spec = spack.store.STORE.db.query_one("callpath ^mpich", installed=installed)
assert spec == callpath_spec assert spec == callpath_spec
spec = spack.store.STORE.db.query_one("callpath ^mpich", installed=any) spec = spack.store.STORE.db.query_one("callpath ^mpich", installed=InstallRecordStatus.ANY)
assert spec == callpath_spec assert spec == callpath_spec
spec = spack.store.STORE.db.query_one("callpath ^mpich", installed=not installed) spec = spack.store.STORE.db.query_one("callpath ^mpich", installed=not installed)

View File

@ -34,6 +34,7 @@
import spack.spec import spack.spec
import spack.store import spack.store
import spack.version as vn import spack.version as vn
from spack.enums import InstallRecordStatus
from spack.installer import PackageInstaller from spack.installer import PackageInstaller
from spack.schema.database_index import schema from spack.schema.database_index import schema
from spack.util.executable import Executable from spack.util.executable import Executable
@ -292,7 +293,7 @@ def _print_ref_counts():
recs = [] recs = []
def add_rec(spec): def add_rec(spec):
cspecs = spack.store.STORE.db.query(spec, installed=any) cspecs = spack.store.STORE.db.query(spec, installed=InstallRecordStatus.ANY)
if not cspecs: if not cspecs:
recs.append("[ %-7s ] %-20s-" % ("", spec)) recs.append("[ %-7s ] %-20s-" % ("", spec))
@ -324,7 +325,7 @@ def add_rec(spec):
def _check_merkleiness(): def _check_merkleiness():
"""Ensure the spack database is a valid merkle graph.""" """Ensure the spack database is a valid merkle graph."""
all_specs = spack.store.STORE.db.query(installed=any) all_specs = spack.store.STORE.db.query(installed=InstallRecordStatus.ANY)
seen = {} seen = {}
for spec in all_specs: for spec in all_specs:
@ -617,7 +618,7 @@ def test_080_root_ref_counts(mutable_database):
mutable_database.remove("mpileaks ^mpich") mutable_database.remove("mpileaks ^mpich")
# record no longer in DB # record no longer in DB
assert mutable_database.query("mpileaks ^mpich", installed=any) == [] assert mutable_database.query("mpileaks ^mpich", installed=InstallRecordStatus.ANY) == []
# record's deps have updated ref_counts # record's deps have updated ref_counts
assert mutable_database.get_record("callpath ^mpich").ref_count == 0 assert mutable_database.get_record("callpath ^mpich").ref_count == 0
@ -627,7 +628,7 @@ def test_080_root_ref_counts(mutable_database):
mutable_database.add(rec.spec) mutable_database.add(rec.spec)
# record is present again # record is present again
assert len(mutable_database.query("mpileaks ^mpich", installed=any)) == 1 assert len(mutable_database.query("mpileaks ^mpich", installed=InstallRecordStatus.ANY)) == 1
# dependencies have ref counts updated # dependencies have ref counts updated
assert mutable_database.get_record("callpath ^mpich").ref_count == 1 assert mutable_database.get_record("callpath ^mpich").ref_count == 1
@ -643,18 +644,21 @@ def test_090_non_root_ref_counts(mutable_database):
# record still in DB but marked uninstalled # record still in DB but marked uninstalled
assert mutable_database.query("callpath ^mpich", installed=True) == [] assert mutable_database.query("callpath ^mpich", installed=True) == []
assert len(mutable_database.query("callpath ^mpich", installed=any)) == 1 assert len(mutable_database.query("callpath ^mpich", installed=InstallRecordStatus.ANY)) == 1
# record and its deps have same ref_counts # record and its deps have same ref_counts
assert mutable_database.get_record("callpath ^mpich", installed=any).ref_count == 1 assert (
mutable_database.get_record("callpath ^mpich", installed=InstallRecordStatus.ANY).ref_count
== 1
)
assert mutable_database.get_record("mpich").ref_count == 2 assert mutable_database.get_record("mpich").ref_count == 2
# remove only dependent of uninstalled callpath record # remove only dependent of uninstalled callpath record
mutable_database.remove("mpileaks ^mpich") mutable_database.remove("mpileaks ^mpich")
# record and parent are completely gone. # record and parent are completely gone.
assert mutable_database.query("mpileaks ^mpich", installed=any) == [] assert mutable_database.query("mpileaks ^mpich", installed=InstallRecordStatus.ANY) == []
assert mutable_database.query("callpath ^mpich", installed=any) == [] assert mutable_database.query("callpath ^mpich", installed=InstallRecordStatus.ANY) == []
# mpich ref count updated properly. # mpich ref count updated properly.
mpich_rec = mutable_database.get_record("mpich") mpich_rec = mutable_database.get_record("mpich")
@ -668,14 +672,14 @@ def fail_while_writing():
raise Exception() raise Exception()
with database.read_transaction(): with database.read_transaction():
assert len(database.query("mpileaks ^zmpi", installed=any)) == 1 assert len(database.query("mpileaks ^zmpi", installed=InstallRecordStatus.ANY)) == 1
with pytest.raises(Exception): with pytest.raises(Exception):
fail_while_writing() fail_while_writing()
# reload DB and make sure zmpi is still there. # reload DB and make sure zmpi is still there.
with database.read_transaction(): with database.read_transaction():
assert len(database.query("mpileaks ^zmpi", installed=any)) == 1 assert len(database.query("mpileaks ^zmpi", installed=InstallRecordStatus.ANY)) == 1
def test_110_no_write_with_exception_on_install(database): def test_110_no_write_with_exception_on_install(database):
@ -685,14 +689,14 @@ def fail_while_writing():
raise Exception() raise Exception()
with database.read_transaction(): with database.read_transaction():
assert database.query("cmake", installed=any) == [] assert database.query("cmake", installed=InstallRecordStatus.ANY) == []
with pytest.raises(Exception): with pytest.raises(Exception):
fail_while_writing() fail_while_writing()
# reload DB and make sure cmake was not written. # reload DB and make sure cmake was not written.
with database.read_transaction(): with database.read_transaction():
assert database.query("cmake", installed=any) == [] assert database.query("cmake", installed=InstallRecordStatus.ANY) == []
def test_115_reindex_with_packages_not_in_repo(mutable_database, tmpdir): def test_115_reindex_with_packages_not_in_repo(mutable_database, tmpdir):

View File

@ -1206,7 +1206,7 @@ _spack_fetch() {
_spack_find() { _spack_find() {
if $list_options if $list_options
then then
SPACK_COMPREPLY="-h --help --format -H --hashes --json -I --install-status -d --deps -p --paths --groups --no-groups -l --long -L --very-long -t --tag -N --namespaces -r --only-roots -c --show-concretized -f --show-flags --show-full-compiler -x --explicit -X --implicit -u --unknown -m --missing -v --variants --loaded -M --only-missing --deprecated --only-deprecated --install-tree --start-date --end-date" SPACK_COMPREPLY="-h --help --format -H --hashes --json -I --install-status -d --deps -p --paths --groups --no-groups -l --long -L --very-long -t --tag -N --namespaces -r --only-roots -c --show-concretized -f --show-flags --show-full-compiler -x --explicit -X --implicit -u --unknown -m --missing -v --variants --loaded -M --only-missing --only-deprecated --deprecated --install-tree --start-date --end-date"
else else
_installed_packages _installed_packages
fi fi

View File

@ -1776,7 +1776,7 @@ complete -c spack -n '__fish_spack_using_command fetch' -l deprecated -f -a conf
complete -c spack -n '__fish_spack_using_command fetch' -l deprecated -d 'allow concretizer to select deprecated versions' complete -c spack -n '__fish_spack_using_command fetch' -l deprecated -d 'allow concretizer to select deprecated versions'
# spack find # spack find
set -g __fish_spack_optspecs_spack_find h/help format= H/hashes json I/install-status d/deps p/paths groups no-groups l/long L/very-long t/tag= N/namespaces r/only-roots c/show-concretized f/show-flags show-full-compiler x/explicit X/implicit u/unknown m/missing v/variants loaded M/only-missing deprecated only-deprecated install-tree= start-date= end-date= set -g __fish_spack_optspecs_spack_find h/help format= H/hashes json I/install-status d/deps p/paths groups no-groups l/long L/very-long t/tag= N/namespaces r/only-roots c/show-concretized f/show-flags show-full-compiler x/explicit X/implicit u/unknown m/missing v/variants loaded M/only-missing only-deprecated deprecated install-tree= start-date= end-date=
complete -c spack -n '__fish_spack_using_command_pos_remainder 0 find' -f -a '(__fish_spack_installed_specs)' complete -c spack -n '__fish_spack_using_command_pos_remainder 0 find' -f -a '(__fish_spack_installed_specs)'
complete -c spack -n '__fish_spack_using_command find' -s h -l help -f -a help complete -c spack -n '__fish_spack_using_command find' -s h -l help -f -a help
complete -c spack -n '__fish_spack_using_command find' -s h -l help -d 'show this help message and exit' complete -c spack -n '__fish_spack_using_command find' -s h -l help -d 'show this help message and exit'
@ -1826,10 +1826,10 @@ complete -c spack -n '__fish_spack_using_command find' -l loaded -f -a loaded
complete -c spack -n '__fish_spack_using_command find' -l loaded -d 'show only packages loaded in the user environment' complete -c spack -n '__fish_spack_using_command find' -l loaded -d 'show only packages loaded in the user environment'
complete -c spack -n '__fish_spack_using_command find' -s M -l only-missing -f -a only_missing complete -c spack -n '__fish_spack_using_command find' -s M -l only-missing -f -a only_missing
complete -c spack -n '__fish_spack_using_command find' -s M -l only-missing -d 'show only missing dependencies' complete -c spack -n '__fish_spack_using_command find' -s M -l only-missing -d 'show only missing dependencies'
complete -c spack -n '__fish_spack_using_command find' -l deprecated -f -a deprecated
complete -c spack -n '__fish_spack_using_command find' -l deprecated -d 'show deprecated packages as well as installed specs'
complete -c spack -n '__fish_spack_using_command find' -l only-deprecated -f -a only_deprecated complete -c spack -n '__fish_spack_using_command find' -l only-deprecated -f -a only_deprecated
complete -c spack -n '__fish_spack_using_command find' -l only-deprecated -d 'show only deprecated packages' complete -c spack -n '__fish_spack_using_command find' -l only-deprecated -d 'show only deprecated packages'
complete -c spack -n '__fish_spack_using_command find' -l deprecated -f -a deprecated
complete -c spack -n '__fish_spack_using_command find' -l deprecated -d 'show deprecated packages as well as installed specs'
complete -c spack -n '__fish_spack_using_command find' -l install-tree -r -f -a install_tree complete -c spack -n '__fish_spack_using_command find' -l install-tree -r -f -a install_tree
complete -c spack -n '__fish_spack_using_command find' -l install-tree -r -d 'Install trees to query: '"'"'all'"'"' (default), '"'"'local'"'"', '"'"'upstream'"'"', upstream name or path' complete -c spack -n '__fish_spack_using_command find' -l install-tree -r -d 'Install trees to query: '"'"'all'"'"' (default), '"'"'local'"'"', '"'"'upstream'"'"', upstream name or path'
complete -c spack -n '__fish_spack_using_command find' -l start-date -r -f -a start_date complete -c spack -n '__fish_spack_using_command find' -l start-date -r -f -a start_date