Move "installed" and "installed_upstream" from PackageBase to Spec (#30191)
This PR moves the `installed` and `installed_upstream` properties from `PackageBase` to `Spec` and is a step towards being able to reuse specs for which we don't have a `package.py` available. It _should_ be sufficient to complete the concretization step and see the spec in the concretized DAG. To fully reuse a spec without a package.py though we need a way to serialize enough data to reconstruct the results of calls to: - `Spec.libs`, `Spec.headers` and `Spec.ommand` - `Package.setup_dependent_*_environment` and `Package.setup_run_environment` - [x] Add stub methods to packages with warnings - [x] Add a missing "root=False" in cmd/fetch.py - [x] Assert that a spec is concrete before checking installation status
This commit is contained in:
parent
58ee164777
commit
a9fbc0175d
@ -1568,12 +1568,11 @@ def install_root_node(spec, allow_root, unsigned=False, force=False, sha256=None
|
|||||||
sha256 (str): optional sha256 of the binary package, to be checked
|
sha256 (str): optional sha256 of the binary package, to be checked
|
||||||
before installation
|
before installation
|
||||||
"""
|
"""
|
||||||
package = spack.repo.get(spec)
|
|
||||||
# Early termination
|
# Early termination
|
||||||
if spec.external or spec.virtual:
|
if spec.external or spec.virtual:
|
||||||
warnings.warn("Skipping external or virtual package {0}".format(spec.format()))
|
warnings.warn("Skipping external or virtual package {0}".format(spec.format()))
|
||||||
return
|
return
|
||||||
elif spec.concrete and package.installed and not force:
|
elif spec.concrete and spec.installed and not force:
|
||||||
warnings.warn("Package for spec {0} already installed.".format(spec.format()))
|
warnings.warn("Package for spec {0} already installed.".format(spec.format()))
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -91,8 +91,8 @@ def dev_build(self, args):
|
|||||||
spec.concretize()
|
spec.concretize()
|
||||||
package = spack.repo.get(spec)
|
package = spack.repo.get(spec)
|
||||||
|
|
||||||
if package.installed:
|
if spec.installed:
|
||||||
tty.error("Already installed in %s" % package.prefix)
|
tty.error("Already installed in %s" % spec.prefix)
|
||||||
tty.msg("Uninstall or try adding a version suffix for this dev build.")
|
tty.msg("Uninstall or try adding a version suffix for this dev build.")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
@ -69,14 +69,10 @@ def fetch(parser, args):
|
|||||||
|
|
||||||
for spec in specs:
|
for spec in specs:
|
||||||
if args.missing or args.dependencies:
|
if args.missing or args.dependencies:
|
||||||
for s in spec.traverse():
|
for s in spec.traverse(root=False):
|
||||||
package = spack.repo.get(s)
|
|
||||||
|
|
||||||
# Skip already-installed packages with --missing
|
# Skip already-installed packages with --missing
|
||||||
if args.missing and package.installed:
|
if args.missing and s.installed:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
package.do_fetch()
|
s.package.do_fetch()
|
||||||
|
spec.package.do_fetch()
|
||||||
package = spack.repo.get(spec)
|
|
||||||
package.do_fetch()
|
|
||||||
|
@ -273,7 +273,7 @@ def refresh(module_type, specs, args):
|
|||||||
return
|
return
|
||||||
|
|
||||||
if not args.upstream_modules:
|
if not args.upstream_modules:
|
||||||
specs = list(s for s in specs if not s.package.installed_upstream)
|
specs = list(s for s in specs if not s.installed_upstream)
|
||||||
|
|
||||||
if not args.yes_to_all:
|
if not args.yes_to_all:
|
||||||
msg = 'You are about to regenerate {types} module files for:\n'
|
msg = 'You are about to regenerate {types} module files for:\n'
|
||||||
|
@ -302,7 +302,7 @@ def _is_dev_spec_and_has_changed(spec):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
# Now we can check whether the code changed since the last installation
|
# Now we can check whether the code changed since the last installation
|
||||||
if not spec.package.installed:
|
if not spec.installed:
|
||||||
# Not installed -> nothing to compare against
|
# Not installed -> nothing to compare against
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -315,7 +315,7 @@ def _spec_needs_overwrite(spec, changed_dev_specs):
|
|||||||
"""Check whether the current spec needs to be overwritten because either it has
|
"""Check whether the current spec needs to be overwritten because either it has
|
||||||
changed itself or one of its dependencies have changed"""
|
changed itself or one of its dependencies have changed"""
|
||||||
# if it's not installed, we don't need to overwrite it
|
# if it's not installed, we don't need to overwrite it
|
||||||
if not spec.package.installed:
|
if not spec.installed:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# If the spec itself has changed this is a trivial decision
|
# If the spec itself has changed this is a trivial decision
|
||||||
@ -330,7 +330,7 @@ def _spec_needs_overwrite(spec, changed_dev_specs):
|
|||||||
# If any dep needs overwrite, or any dep is missing and is a dev build then
|
# If any dep needs overwrite, or any dep is missing and is a dev build then
|
||||||
# overwrite this package
|
# overwrite this package
|
||||||
if any(
|
if any(
|
||||||
((not dep.package.installed) and dep.satisfies('dev_path=*')) or
|
((not dep.installed) and dep.satisfies('dev_path=*')) or
|
||||||
_spec_needs_overwrite(dep, changed_dev_specs)
|
_spec_needs_overwrite(dep, changed_dev_specs)
|
||||||
for dep in spec.traverse(root=False)
|
for dep in spec.traverse(root=False)
|
||||||
):
|
):
|
||||||
@ -518,7 +518,7 @@ def specs_for_view(self, concretized_root_specs):
|
|||||||
|
|
||||||
# Filter selected, installed specs
|
# Filter selected, installed specs
|
||||||
with spack.store.db.read_transaction():
|
with spack.store.db.read_transaction():
|
||||||
specs = [s for s in specs if s in self and s.package.installed]
|
specs = [s for s in specs if s in self and s.installed]
|
||||||
|
|
||||||
return specs
|
return specs
|
||||||
|
|
||||||
@ -1380,9 +1380,10 @@ def check_views(self):
|
|||||||
# default view if they are installed.
|
# default view if they are installed.
|
||||||
for view_name, view in self.views.items():
|
for view_name, view in self.views.items():
|
||||||
for _, spec in self.concretized_specs():
|
for _, spec in self.concretized_specs():
|
||||||
if spec in view and spec.package.installed:
|
if spec in view and spec.package and spec.installed:
|
||||||
tty.debug(
|
msg = '{0} in view "{1}"'
|
||||||
'Spec %s in view %s' % (spec.name, view_name))
|
tty.debug(msg.format(spec.name, view_name))
|
||||||
|
|
||||||
except (spack.repo.UnknownPackageError,
|
except (spack.repo.UnknownPackageError,
|
||||||
spack.repo.UnknownNamespaceError) as e:
|
spack.repo.UnknownNamespaceError) as e:
|
||||||
tty.warn(e)
|
tty.warn(e)
|
||||||
@ -1398,7 +1399,8 @@ def _env_modifications_for_default_view(self, reverse=False):
|
|||||||
|
|
||||||
errors = []
|
errors = []
|
||||||
for _, root_spec in self.concretized_specs():
|
for _, root_spec in self.concretized_specs():
|
||||||
if root_spec in self.default_view and root_spec.package.installed:
|
if (root_spec in self.default_view and
|
||||||
|
root_spec.installed and root_spec.package):
|
||||||
for spec in root_spec.traverse(deptype='run', root=True):
|
for spec in root_spec.traverse(deptype='run', root=True):
|
||||||
if spec.name in visited:
|
if spec.name in visited:
|
||||||
# It is expected that only one instance of the package
|
# It is expected that only one instance of the package
|
||||||
@ -1537,7 +1539,7 @@ def uninstalled_specs(self):
|
|||||||
with spack.store.db.read_transaction():
|
with spack.store.db.read_transaction():
|
||||||
for concretized_hash in self.concretized_order:
|
for concretized_hash in self.concretized_order:
|
||||||
spec = self.specs_by_hash[concretized_hash]
|
spec = self.specs_by_hash[concretized_hash]
|
||||||
if not spec.package.installed or (
|
if not spec.installed or (
|
||||||
spec.satisfies('dev_path=*') or
|
spec.satisfies('dev_path=*') or
|
||||||
spec.satisfies('^dev_path=*')
|
spec.satisfies('^dev_path=*')
|
||||||
):
|
):
|
||||||
@ -1572,7 +1574,7 @@ def install_specs(self, specs=None, **install_args):
|
|||||||
|
|
||||||
# ensure specs already installed are marked explicit
|
# ensure specs already installed are marked explicit
|
||||||
all_specs = specs or [cs for _, cs in self.concretized_specs()]
|
all_specs = specs or [cs for _, cs in self.concretized_specs()]
|
||||||
specs_installed = [s for s in all_specs if s.package.installed]
|
specs_installed = [s for s in all_specs if s.installed]
|
||||||
with spack.store.db.write_transaction(): # do all in one transaction
|
with spack.store.db.write_transaction(): # do all in one transaction
|
||||||
for spec in specs_installed:
|
for spec in specs_installed:
|
||||||
spack.store.db.update_explicit(spec, True)
|
spack.store.db.update_explicit(spec, True)
|
||||||
@ -1599,7 +1601,7 @@ def install_specs(self, specs=None, **install_args):
|
|||||||
finally:
|
finally:
|
||||||
# Ensure links are set appropriately
|
# Ensure links are set appropriately
|
||||||
for spec in specs_to_install:
|
for spec in specs_to_install:
|
||||||
if spec.package.installed:
|
if spec.installed:
|
||||||
self.new_installs.append(spec)
|
self.new_installs.append(spec)
|
||||||
try:
|
try:
|
||||||
self._install_log_links(spec)
|
self._install_log_links(spec)
|
||||||
@ -1649,7 +1651,7 @@ def added_specs(self):
|
|||||||
concrete = concretized.get(spec)
|
concrete = concretized.get(spec)
|
||||||
if not concrete:
|
if not concrete:
|
||||||
yield spec
|
yield spec
|
||||||
elif not concrete.package.installed:
|
elif not concrete.installed:
|
||||||
yield concrete
|
yield concrete
|
||||||
|
|
||||||
def concretized_specs(self):
|
def concretized_specs(self):
|
||||||
|
@ -140,7 +140,7 @@ def _handle_external_and_upstream(pkg, explicit):
|
|||||||
.format(pkg.prefix, package_id(pkg)))
|
.format(pkg.prefix, package_id(pkg)))
|
||||||
return True
|
return True
|
||||||
|
|
||||||
if pkg.installed_upstream:
|
if pkg.spec.installed_upstream:
|
||||||
tty.verbose('{0} is installed in an upstream Spack instance at {1}'
|
tty.verbose('{0} is installed in an upstream Spack instance at {1}'
|
||||||
.format(package_id(pkg), pkg.spec.prefix))
|
.format(package_id(pkg), pkg.spec.prefix))
|
||||||
_print_installed_pkg(pkg.prefix)
|
_print_installed_pkg(pkg.prefix)
|
||||||
@ -853,7 +853,7 @@ def _check_deps_status(self, request):
|
|||||||
raise InstallError(err.format(request.pkg_id, msg))
|
raise InstallError(err.format(request.pkg_id, msg))
|
||||||
|
|
||||||
# Flag external and upstream packages as being installed
|
# Flag external and upstream packages as being installed
|
||||||
if dep_pkg.spec.external or dep_pkg.installed_upstream:
|
if dep_pkg.spec.external or dep_pkg.spec.installed_upstream:
|
||||||
self._flag_installed(dep_pkg)
|
self._flag_installed(dep_pkg)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@ -995,7 +995,7 @@ def _ensure_install_ready(self, pkg):
|
|||||||
raise ExternalPackageError('{0} {1}'.format(pre, 'is external'))
|
raise ExternalPackageError('{0} {1}'.format(pre, 'is external'))
|
||||||
|
|
||||||
# Upstream packages cannot be installed locally.
|
# Upstream packages cannot be installed locally.
|
||||||
if pkg.installed_upstream:
|
if pkg.spec.installed_upstream:
|
||||||
raise UpstreamPackageError('{0} {1}'.format(pre, 'is upstream'))
|
raise UpstreamPackageError('{0} {1}'.format(pre, 'is upstream'))
|
||||||
|
|
||||||
# The package must have a prefix lock at this stage.
|
# The package must have a prefix lock at this stage.
|
||||||
|
@ -370,7 +370,7 @@ def get_module(
|
|||||||
available.
|
available.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
upstream = spec.package.installed_upstream
|
upstream = spec.installed_upstream
|
||||||
except spack.repo.UnknownPackageError:
|
except spack.repo.UnknownPackageError:
|
||||||
upstream, record = spack.store.db.query_by_spec_hash(spec.dag_hash())
|
upstream, record = spack.store.db.query_by_spec_hash(spec.dag_hash())
|
||||||
if upstream:
|
if upstream:
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
import time
|
import time
|
||||||
import traceback
|
import traceback
|
||||||
import types
|
import types
|
||||||
|
import warnings
|
||||||
from typing import Any, Callable, Dict, List, Optional # novm
|
from typing import Any, Callable, Dict, List, Optional # novm
|
||||||
|
|
||||||
import six
|
import six
|
||||||
@ -790,15 +791,6 @@ def __init__(self, spec):
|
|||||||
|
|
||||||
super(PackageBase, self).__init__()
|
super(PackageBase, self).__init__()
|
||||||
|
|
||||||
@property
|
|
||||||
def installed_upstream(self):
|
|
||||||
if not hasattr(self, '_installed_upstream'):
|
|
||||||
upstream, record = spack.store.db.query_by_spec_hash(
|
|
||||||
self.spec.dag_hash())
|
|
||||||
self._installed_upstream = upstream
|
|
||||||
|
|
||||||
return self._installed_upstream
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def possible_dependencies(
|
def possible_dependencies(
|
||||||
cls, transitive=True, expand_virtuals=True, deptype='all',
|
cls, transitive=True, expand_virtuals=True, deptype='all',
|
||||||
@ -1267,6 +1259,20 @@ def install_test_root(self):
|
|||||||
"""Return the install test root directory."""
|
"""Return the install test root directory."""
|
||||||
return os.path.join(self.metadata_dir, 'test')
|
return os.path.join(self.metadata_dir, 'test')
|
||||||
|
|
||||||
|
@property
|
||||||
|
def installed(self):
|
||||||
|
msg = ('the "PackageBase.installed" property is deprecated and will be '
|
||||||
|
'removed in Spack v0.19, use "Spec.installed" instead')
|
||||||
|
warnings.warn(msg)
|
||||||
|
return self.spec.installed
|
||||||
|
|
||||||
|
@property
|
||||||
|
def installed_upstream(self):
|
||||||
|
msg = ('the "PackageBase.installed_upstream" property is deprecated and will '
|
||||||
|
'be removed in Spack v0.19, use "Spec.installed_upstream" instead')
|
||||||
|
warnings.warn(msg)
|
||||||
|
return self.spec.installed_upstream
|
||||||
|
|
||||||
def _make_fetcher(self):
|
def _make_fetcher(self):
|
||||||
# Construct a composite fetcher that always contains at least
|
# Construct a composite fetcher that always contains at least
|
||||||
# one element (the root package). In case there are resources
|
# one element (the root package). In case there are resources
|
||||||
@ -1380,7 +1386,7 @@ def is_activated(self, view):
|
|||||||
if not self.is_extension:
|
if not self.is_extension:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"is_activated called on package that is not an extension.")
|
"is_activated called on package that is not an extension.")
|
||||||
if self.extendee_spec.package.installed_upstream:
|
if self.extendee_spec.installed_upstream:
|
||||||
# If this extends an upstream package, it cannot be activated for
|
# If this extends an upstream package, it cannot be activated for
|
||||||
# it. This bypasses construction of the extension map, which can
|
# it. This bypasses construction of the extension map, which can
|
||||||
# can fail when run in the context of a downstream Spack instance
|
# can fail when run in the context of a downstream Spack instance
|
||||||
@ -1406,22 +1412,6 @@ def virtuals_provided(self):
|
|||||||
return [vspec for vspec, constraints in self.provided.items()
|
return [vspec for vspec, constraints in self.provided.items()
|
||||||
if any(self.spec.satisfies(c) for c in constraints)]
|
if any(self.spec.satisfies(c) for c in constraints)]
|
||||||
|
|
||||||
@property
|
|
||||||
def installed(self):
|
|
||||||
"""Installation status of a package.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
True if the package has been installed, False otherwise.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
# If the spec is in the DB, check the installed
|
|
||||||
# attribute of the record
|
|
||||||
return spack.store.db.get_record(self.spec).installed
|
|
||||||
except KeyError:
|
|
||||||
# If the spec is not in the DB, the method
|
|
||||||
# above raises a Key error
|
|
||||||
return False
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def prefix(self):
|
def prefix(self):
|
||||||
"""Get the prefix into which this package should be installed."""
|
"""Get the prefix into which this package should be installed."""
|
||||||
@ -2143,21 +2133,21 @@ def build_log_path(self):
|
|||||||
to the staging build file until the software is successfully installed,
|
to the staging build file until the software is successfully installed,
|
||||||
when it points to the file in the installation directory.
|
when it points to the file in the installation directory.
|
||||||
"""
|
"""
|
||||||
return self.install_log_path if self.installed else self.log_path
|
return self.install_log_path if self.spec.installed else self.log_path
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def inject_flags(cls, name, flags):
|
def inject_flags(cls, name, flags):
|
||||||
"""
|
"""
|
||||||
flag_handler that injects all flags through the compiler wrapper.
|
flag_handler that injects all flags through the compiler wrapper.
|
||||||
"""
|
"""
|
||||||
return (flags, None, None)
|
return flags, None, None
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def env_flags(cls, name, flags):
|
def env_flags(cls, name, flags):
|
||||||
"""
|
"""
|
||||||
flag_handler that adds all flags to canonical environment variables.
|
flag_handler that adds all flags to canonical environment variables.
|
||||||
"""
|
"""
|
||||||
return (None, flags, None)
|
return None, flags, None
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def build_system_flags(cls, name, flags):
|
def build_system_flags(cls, name, flags):
|
||||||
@ -2168,7 +2158,7 @@ def build_system_flags(cls, name, flags):
|
|||||||
implements it. Currently, AutotoolsPackage and CMakePackage
|
implements it. Currently, AutotoolsPackage and CMakePackage
|
||||||
implement it.
|
implement it.
|
||||||
"""
|
"""
|
||||||
return (None, None, flags)
|
return None, None, flags
|
||||||
|
|
||||||
def setup_build_environment(self, env):
|
def setup_build_environment(self, env):
|
||||||
"""Sets up the build environment for a package.
|
"""Sets up the build environment for a package.
|
||||||
@ -2465,10 +2455,10 @@ def _sanity_check_extension(self):
|
|||||||
extendee_package = self.extendee_spec.package
|
extendee_package = self.extendee_spec.package
|
||||||
extendee_package._check_extendable()
|
extendee_package._check_extendable()
|
||||||
|
|
||||||
if not extendee_package.installed:
|
if not self.extendee_spec.installed:
|
||||||
raise ActivationError(
|
raise ActivationError(
|
||||||
"Can only (de)activate extensions for installed packages.")
|
"Can only (de)activate extensions for installed packages.")
|
||||||
if not self.installed:
|
if not self.spec.installed:
|
||||||
raise ActivationError("Extensions must first be installed.")
|
raise ActivationError("Extensions must first be installed.")
|
||||||
if self.extendee_spec.name not in self.extendees:
|
if self.extendee_spec.name not in self.extendees:
|
||||||
raise ActivationError("%s does not extend %s!" %
|
raise ActivationError("%s does not extend %s!" %
|
||||||
|
@ -112,8 +112,7 @@ def __enter__(self):
|
|||||||
# Check which specs are already installed and mark them as skipped
|
# Check which specs are already installed and mark them as skipped
|
||||||
# only for install_task
|
# only for install_task
|
||||||
if self.do_fn == '_install_task':
|
if self.do_fn == '_install_task':
|
||||||
for dep in filter(lambda x: x.package.installed,
|
for dep in filter(lambda x: x.installed, input_spec.traverse()):
|
||||||
input_spec.traverse()):
|
|
||||||
package = {
|
package = {
|
||||||
'name': dep.name,
|
'name': dep.name,
|
||||||
'id': dep.dag_hash(),
|
'id': dep.dag_hash(),
|
||||||
@ -140,7 +139,7 @@ def wrapper(instance, *args, **kwargs):
|
|||||||
raise Exception
|
raise Exception
|
||||||
|
|
||||||
# We accounted before for what is already installed
|
# We accounted before for what is already installed
|
||||||
installed_already = pkg.installed
|
installed_already = pkg.spec.installed
|
||||||
|
|
||||||
package = {
|
package = {
|
||||||
'name': pkg.name,
|
'name': pkg.name,
|
||||||
|
@ -38,13 +38,13 @@ def rewire(spliced_spec):
|
|||||||
nodes in the DAG of that spec."""
|
nodes in the DAG of that spec."""
|
||||||
assert spliced_spec.spliced
|
assert spliced_spec.spliced
|
||||||
for spec in spliced_spec.traverse(order='post', root=True):
|
for spec in spliced_spec.traverse(order='post', root=True):
|
||||||
if not spec.build_spec.package.installed:
|
if not spec.build_spec.installed:
|
||||||
# TODO: May want to change this at least for the root spec...
|
# TODO: May want to change this at least for the root spec...
|
||||||
# spec.build_spec.package.do_install(force=True)
|
# spec.build_spec.package.do_install(force=True)
|
||||||
raise PackageNotInstalledError(spliced_spec,
|
raise PackageNotInstalledError(spliced_spec,
|
||||||
spec.build_spec,
|
spec.build_spec,
|
||||||
spec)
|
spec)
|
||||||
if spec.build_spec is not spec and not spec.package.installed:
|
if spec.build_spec is not spec and not spec.installed:
|
||||||
explicit = spec is spliced_spec
|
explicit = spec is spliced_spec
|
||||||
rewire_node(spec, explicit)
|
rewire_node(spec, explicit)
|
||||||
|
|
||||||
|
@ -1197,6 +1197,7 @@ def __init__(self, spec_like=None, normal=False,
|
|||||||
self._package_hash = None
|
self._package_hash = None
|
||||||
self._dunder_hash = None
|
self._dunder_hash = None
|
||||||
self._package = None
|
self._package = None
|
||||||
|
self._installed_upstream = None
|
||||||
|
|
||||||
# Most of these are internal implementation details that can be
|
# Most of these are internal implementation details that can be
|
||||||
# set by internal Spack calls in the constructor.
|
# set by internal Spack calls in the constructor.
|
||||||
@ -1554,6 +1555,33 @@ def spliced(self):
|
|||||||
"""
|
"""
|
||||||
return any(s.build_spec is not s for s in self.traverse(root=True))
|
return any(s.build_spec is not s for s in self.traverse(root=True))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def installed(self):
|
||||||
|
"""Installation status of a package.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
True if the package has been installed, False otherwise.
|
||||||
|
"""
|
||||||
|
msg = "a spec must be concrete to be queried for installation status"
|
||||||
|
assert self.concrete, msg
|
||||||
|
try:
|
||||||
|
# If the spec is in the DB, check the installed
|
||||||
|
# attribute of the record
|
||||||
|
return spack.store.db.get_record(self).installed
|
||||||
|
except KeyError:
|
||||||
|
# If the spec is not in the DB, the method
|
||||||
|
# above raises a Key error
|
||||||
|
return False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def installed_upstream(self):
|
||||||
|
msg = "a spec must be concrete to be queried for installation status"
|
||||||
|
assert self.concrete, msg
|
||||||
|
if getattr(self, '_installed_upstream', None) is None:
|
||||||
|
upstream, _ = spack.store.db.query_by_spec_hash(self.dag_hash())
|
||||||
|
self._installed_upstream = upstream
|
||||||
|
return self._installed_upstream
|
||||||
|
|
||||||
def traverse(self, **kwargs):
|
def traverse(self, **kwargs):
|
||||||
direction = kwargs.get('direction', 'children')
|
direction = kwargs.get('direction', 'children')
|
||||||
depth = kwargs.get('depth', False)
|
depth = kwargs.get('depth', False)
|
||||||
@ -2880,7 +2908,7 @@ def concretize(self, tests=False):
|
|||||||
|
|
||||||
def _mark_root_concrete(self, value=True):
|
def _mark_root_concrete(self, value=True):
|
||||||
"""Mark just this spec (not dependencies) concrete."""
|
"""Mark just this spec (not dependencies) concrete."""
|
||||||
if (not value) and self.concrete and self.package.installed:
|
if (not value) and self.concrete and self.installed:
|
||||||
return
|
return
|
||||||
self._normal = value
|
self._normal = value
|
||||||
self._concrete = value
|
self._concrete = value
|
||||||
@ -2894,7 +2922,7 @@ def _mark_concrete(self, value=True):
|
|||||||
# if set to false, clear out all hashes (set to None or remove attr)
|
# if set to false, clear out all hashes (set to None or remove attr)
|
||||||
# may need to change references to respect None
|
# may need to change references to respect None
|
||||||
for s in self.traverse():
|
for s in self.traverse():
|
||||||
if (not value) and s.concrete and s.package.installed:
|
if (not value) and s.concrete and s.installed:
|
||||||
continue
|
continue
|
||||||
elif not value:
|
elif not value:
|
||||||
s.clear_cached_hashes()
|
s.clear_cached_hashes()
|
||||||
@ -3159,7 +3187,7 @@ def _normalize_helper(self, visited, spec_deps, provider_index, tests):
|
|||||||
# Avoid recursively adding constraints for already-installed packages:
|
# Avoid recursively adding constraints for already-installed packages:
|
||||||
# these may include build dependencies which are not needed for this
|
# these may include build dependencies which are not needed for this
|
||||||
# install (since this package is already installed).
|
# install (since this package is already installed).
|
||||||
if self.concrete and self.package.installed:
|
if self.concrete and self.installed:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Combine constraints from package deps with constraints from
|
# Combine constraints from package deps with constraints from
|
||||||
@ -4529,7 +4557,7 @@ def tree(self, **kwargs):
|
|||||||
|
|
||||||
if status_fn:
|
if status_fn:
|
||||||
status = status_fn(node)
|
status = status_fn(node)
|
||||||
if node.package.installed_upstream:
|
if node.installed_upstream:
|
||||||
out += clr.colorize("@g{[^]} ", color=color)
|
out += clr.colorize("@g{[^]} ", color=color)
|
||||||
elif status is None:
|
elif status is None:
|
||||||
out += clr.colorize("@K{ - } ", color=color) # !installed
|
out += clr.colorize("@K{ - } ", color=color) # !installed
|
||||||
|
@ -162,7 +162,7 @@ def test_env_install_all(install_mockery, mock_fetch):
|
|||||||
e.install_all()
|
e.install_all()
|
||||||
env_specs = e._get_environment_specs()
|
env_specs = e._get_environment_specs()
|
||||||
spec = next(x for x in env_specs if x.name == 'cmake-client')
|
spec = next(x for x in env_specs if x.name == 'cmake-client')
|
||||||
assert spec.package.installed
|
assert spec.installed
|
||||||
|
|
||||||
|
|
||||||
def test_env_install_single_spec(install_mockery, mock_fetch):
|
def test_env_install_single_spec(install_mockery, mock_fetch):
|
||||||
|
@ -1422,7 +1422,7 @@ def test_concrete_specs_are_not_modified_on_reuse(
|
|||||||
# the answer set produced by clingo.
|
# the answer set produced by clingo.
|
||||||
with spack.config.override("concretizer:reuse", True):
|
with spack.config.override("concretizer:reuse", True):
|
||||||
s = spack.spec.Spec(spec_str).concretized()
|
s = spack.spec.Spec(spec_str).concretized()
|
||||||
assert s.package.installed is expect_installed
|
assert s.installed is expect_installed
|
||||||
assert s.satisfies(spec_str, strict=True)
|
assert s.satisfies(spec_str, strict=True)
|
||||||
|
|
||||||
@pytest.mark.regression('26721,19736')
|
@pytest.mark.regression('26721,19736')
|
||||||
|
@ -726,11 +726,11 @@ def test_regression_issue_8036(mutable_database, usr_folder_exists):
|
|||||||
# do_install.
|
# do_install.
|
||||||
s = spack.spec.Spec('externaltool@0.9')
|
s = spack.spec.Spec('externaltool@0.9')
|
||||||
s.concretize()
|
s.concretize()
|
||||||
assert not s.package.installed
|
assert not s.installed
|
||||||
|
|
||||||
# Now install the external package and check again the `installed` property
|
# Now install the external package and check again the `installed` property
|
||||||
s.package.do_install(fake=True)
|
s.package.do_install(fake=True)
|
||||||
assert s.package.installed
|
assert s.installed
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.regression('11118')
|
@pytest.mark.regression('11118')
|
||||||
@ -761,7 +761,7 @@ def test_old_external_entries_prefix(mutable_database):
|
|||||||
def test_uninstall_by_spec(mutable_database):
|
def test_uninstall_by_spec(mutable_database):
|
||||||
with mutable_database.write_transaction():
|
with mutable_database.write_transaction():
|
||||||
for spec in mutable_database.query():
|
for spec in mutable_database.query():
|
||||||
if spec.package.installed:
|
if spec.installed:
|
||||||
spack.package.PackageBase.uninstall_by_spec(spec, force=True)
|
spack.package.PackageBase.uninstall_by_spec(spec, force=True)
|
||||||
else:
|
else:
|
||||||
mutable_database.remove(spec)
|
mutable_database.remove(spec)
|
||||||
@ -1023,3 +1023,19 @@ def test_consistency_of_dependents_upon_remove(mutable_database):
|
|||||||
s = mutable_database.query_one('dyninst')
|
s = mutable_database.query_one('dyninst')
|
||||||
parents = s.dependents(name='callpath')
|
parents = s.dependents(name='callpath')
|
||||||
assert len(parents) == 2
|
assert len(parents) == 2
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.regression('30187')
|
||||||
|
def test_query_installed_when_package_unknown(database):
|
||||||
|
"""Test that we can query the installation status of a spec
|
||||||
|
when we don't know its package.py
|
||||||
|
"""
|
||||||
|
with spack.repo.use_repositories(MockPackageMultiRepo()):
|
||||||
|
specs = database.query('mpileaks')
|
||||||
|
for s in specs:
|
||||||
|
# Assert that we can query the installation methods even though we
|
||||||
|
# don't have the package.py available
|
||||||
|
assert s.installed
|
||||||
|
assert not s.installed_upstream
|
||||||
|
with pytest.raises(spack.repo.UnknownNamespaceError):
|
||||||
|
s.package
|
||||||
|
@ -119,7 +119,7 @@ def test_partial_install_delete_prefix_and_stage(install_mockery, mock_fetch):
|
|||||||
pkg.do_install(restage=True)
|
pkg.do_install(restage=True)
|
||||||
assert rm_prefix_checker.removed
|
assert rm_prefix_checker.removed
|
||||||
assert pkg.stage.test_destroyed
|
assert pkg.stage.test_destroyed
|
||||||
assert pkg.installed
|
assert pkg.spec.installed
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
pkg.remove_prefix = instance_rm_prefix
|
pkg.remove_prefix = instance_rm_prefix
|
||||||
@ -146,7 +146,7 @@ def test_failing_overwrite_install_should_keep_previous_installation(
|
|||||||
with pytest.raises(Exception):
|
with pytest.raises(Exception):
|
||||||
pkg.do_install(**kwargs)
|
pkg.do_install(**kwargs)
|
||||||
|
|
||||||
assert pkg.installed
|
assert pkg.spec.installed
|
||||||
assert os.path.exists(spec.prefix)
|
assert os.path.exists(spec.prefix)
|
||||||
|
|
||||||
|
|
||||||
@ -301,7 +301,7 @@ def test_installed_upstream(install_upstream, mock_fetch):
|
|||||||
dependent = spack.spec.Spec('dependent-install').concretized()
|
dependent = spack.spec.Spec('dependent-install').concretized()
|
||||||
|
|
||||||
new_dependency = dependent['dependency-install']
|
new_dependency = dependent['dependency-install']
|
||||||
assert new_dependency.package.installed_upstream
|
assert new_dependency.installed_upstream
|
||||||
assert (new_dependency.prefix ==
|
assert (new_dependency.prefix ==
|
||||||
upstream_layout.path_for_spec(dependency))
|
upstream_layout.path_for_spec(dependency))
|
||||||
|
|
||||||
@ -333,7 +333,7 @@ def test_partial_install_keep_prefix(install_mockery, mock_fetch, monkeypatch):
|
|||||||
pkg.succeed = True # make the build succeed
|
pkg.succeed = True # make the build succeed
|
||||||
pkg.stage = MockStage(pkg.stage)
|
pkg.stage = MockStage(pkg.stage)
|
||||||
pkg.do_install(keep_prefix=True)
|
pkg.do_install(keep_prefix=True)
|
||||||
assert pkg.installed
|
assert pkg.spec.installed
|
||||||
assert not pkg.stage.test_destroyed
|
assert not pkg.stage.test_destroyed
|
||||||
|
|
||||||
|
|
||||||
@ -344,7 +344,7 @@ def test_second_install_no_overwrite_first(install_mockery, mock_fetch, monkeypa
|
|||||||
|
|
||||||
pkg.succeed = True
|
pkg.succeed = True
|
||||||
pkg.do_install()
|
pkg.do_install()
|
||||||
assert pkg.installed
|
assert pkg.spec.installed
|
||||||
|
|
||||||
# If Package.install is called after this point, it will fail
|
# If Package.install is called after this point, it will fail
|
||||||
pkg.succeed = False
|
pkg.succeed = False
|
||||||
|
@ -300,14 +300,14 @@ def test_installer_ensure_ready_errors(install_mockery):
|
|||||||
|
|
||||||
# Force an upstream package error
|
# Force an upstream package error
|
||||||
spec.external_path, spec.external_modules = path, modules
|
spec.external_path, spec.external_modules = path, modules
|
||||||
spec.package._installed_upstream = True
|
spec._installed_upstream = True
|
||||||
msg = fmt.format('is upstream')
|
msg = fmt.format('is upstream')
|
||||||
with pytest.raises(inst.UpstreamPackageError, match=msg):
|
with pytest.raises(inst.UpstreamPackageError, match=msg):
|
||||||
installer._ensure_install_ready(spec.package)
|
installer._ensure_install_ready(spec.package)
|
||||||
|
|
||||||
# Force an install lock error, which should occur naturally since
|
# Force an install lock error, which should occur naturally since
|
||||||
# we are calling an internal method prior to any lock-related setup
|
# we are calling an internal method prior to any lock-related setup
|
||||||
spec.package._installed_upstream = False
|
spec._installed_upstream = False
|
||||||
assert len(installer.locks) == 0
|
assert len(installer.locks) == 0
|
||||||
with pytest.raises(inst.InstallLockError, match=fmt.format('not locked')):
|
with pytest.raises(inst.InstallLockError, match=fmt.format('not locked')):
|
||||||
installer._ensure_install_ready(spec.package)
|
installer._ensure_install_ready(spec.package)
|
||||||
@ -638,7 +638,7 @@ def test_check_deps_status_upstream(install_mockery, monkeypatch):
|
|||||||
request = installer.build_requests[0]
|
request = installer.build_requests[0]
|
||||||
|
|
||||||
# Mock the known dependent, b, as installed upstream
|
# Mock the known dependent, b, as installed upstream
|
||||||
monkeypatch.setattr(spack.package.PackageBase, 'installed_upstream', True)
|
monkeypatch.setattr(spack.spec.Spec, 'installed_upstream', True)
|
||||||
installer._check_deps_status(request)
|
installer._check_deps_status(request)
|
||||||
assert list(installer.installed)[0].startswith('b')
|
assert list(installer.installed)[0].startswith('b')
|
||||||
|
|
||||||
|
@ -2,8 +2,6 @@
|
|||||||
# Spack Project Developers. See the top-level COPYRIGHT file for details.
|
# Spack Project Developers. See the top-level COPYRIGHT file for details.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||||
|
|
||||||
import collections
|
|
||||||
import os
|
import os
|
||||||
import stat
|
import stat
|
||||||
import sys
|
import sys
|
||||||
@ -208,9 +206,7 @@ def test_get_module_upstream():
|
|||||||
)
|
)
|
||||||
upstream_index = UpstreamModuleIndex(mock_db, module_indices)
|
upstream_index = UpstreamModuleIndex(mock_db, module_indices)
|
||||||
|
|
||||||
MockPackage = collections.namedtuple('MockPackage', ['installed_upstream'])
|
setattr(s1, "installed_upstream", True)
|
||||||
setattr(s1, "package", MockPackage(True))
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
old_index = spack.modules.common.upstream_module_index
|
old_index = spack.modules.common.upstream_module_index
|
||||||
spack.modules.common.upstream_module_index = upstream_index
|
spack.modules.common.upstream_module_index = upstream_index
|
||||||
|
@ -84,7 +84,7 @@ def test_test_deptype():
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.usefixtures('config')
|
@pytest.mark.usefixtures('config')
|
||||||
def test_installed_deps():
|
def test_installed_deps(monkeypatch):
|
||||||
"""Preinstall a package P with a constrained build dependency D, then
|
"""Preinstall a package P with a constrained build dependency D, then
|
||||||
concretize a dependent package which also depends on P and D, specifying
|
concretize a dependent package which also depends on P and D, specifying
|
||||||
that the installed instance of P should be used. In this case, D should
|
that the installed instance of P should be used. In this case, D should
|
||||||
@ -120,9 +120,12 @@ def test_installed_deps():
|
|||||||
assert c_spec['d'].version == spack.version.Version('2')
|
assert c_spec['d'].version == spack.version.Version('2')
|
||||||
|
|
||||||
c_installed = spack.spec.Spec.from_dict(c_spec.to_dict())
|
c_installed = spack.spec.Spec.from_dict(c_spec.to_dict())
|
||||||
for spec in c_installed.traverse():
|
installed_names = [s.name for s in c_installed.traverse()]
|
||||||
setattr(spec.package, 'installed', True)
|
|
||||||
|
|
||||||
|
def _mock_installed(self):
|
||||||
|
return self.name in installed_names
|
||||||
|
|
||||||
|
monkeypatch.setattr(Spec, 'installed', _mock_installed)
|
||||||
a_spec = Spec('a')
|
a_spec = Spec('a')
|
||||||
a_spec._add_dependency(c_installed, default)
|
a_spec._add_dependency(c_installed, default)
|
||||||
a_spec.concretize()
|
a_spec.concretize()
|
||||||
|
@ -432,8 +432,7 @@ def test_is_activated_upstream_extendee(tmpdir, builtin_and_mock_packages,
|
|||||||
# Set the prefix on the package's spec reference because that is a copy of
|
# Set the prefix on the package's spec reference because that is a copy of
|
||||||
# the original spec
|
# the original spec
|
||||||
extendee_spec.package.spec.prefix = python_prefix
|
extendee_spec.package.spec.prefix = python_prefix
|
||||||
monkeypatch.setattr(extendee_spec.package.__class__,
|
monkeypatch.setattr(extendee_spec.__class__, 'installed_upstream', True)
|
||||||
'installed_upstream', True)
|
|
||||||
|
|
||||||
ext_name = 'py-extension1'
|
ext_name = 'py-extension1'
|
||||||
tmpdir.ensure(ext_name, dir=True)
|
tmpdir.ensure(ext_name, dir=True)
|
||||||
|
@ -32,7 +32,6 @@ def __init__(self, dependencies, dependency_types,
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
self.spec = None
|
self.spec = None
|
||||||
self._installed_upstream = False
|
|
||||||
|
|
||||||
def provides(self, vname):
|
def provides(self, vname):
|
||||||
return vname in self.provided
|
return vname in self.provided
|
||||||
|
Loading…
Reference in New Issue
Block a user