Spec.satisfies accesses Spec.concrete as property (#2928)
* Spec.satisfies accesses Spec.concrete as property Fixes #2760 When copying a spec, _concrete is always set to False for each dependency. "Spec.satisfies" was accessing the member "_concrete" directly instead of using the property "concrete". This means that if you copy a spec, the dependencies will be considered equal, but did not necessarily satisfy one another. Spec.satisfies is a prerequisite for a package to be considered an extension; as a consequence, an extension with run-time dependencies that were also extensions did not activate those extensions. This updates Spec.satisfies to avoid checking the cached member "_concrete" directly. * Added test to check for activation of dependency extension * Added test to check for transitive satisfiability between a spec and its copy
This commit is contained in:
parent
596190c83c
commit
e4d2d747ce
7 changed files with 143 additions and 6 deletions
|
@ -1560,10 +1560,9 @@ def do_activate(self, force=False):
|
|||
|
||||
# Activate any package dependencies that are also extensions.
|
||||
if not force:
|
||||
for spec in self.spec.traverse(root=False, deptype='run'):
|
||||
if spec.package.extends(self.extendee_spec):
|
||||
if not spec.package.activated:
|
||||
spec.package.do_activate(force=force)
|
||||
for spec in self.dependency_activations():
|
||||
if not spec.package.activated:
|
||||
spec.package.do_activate(force=force)
|
||||
|
||||
self.extendee_spec.package.activate(self, **self.extendee_args)
|
||||
|
||||
|
@ -1571,6 +1570,10 @@ def do_activate(self, force=False):
|
|||
tty.msg("Activated extension %s for %s" %
|
||||
(self.spec.short_spec, self.extendee_spec.format("$_$@$+$%@")))
|
||||
|
||||
def dependency_activations(self):
|
||||
return (spec for spec in self.spec.traverse(root=False, deptype='run')
|
||||
if spec.package.extends(self.extendee_spec))
|
||||
|
||||
def activate(self, extension, **kwargs):
|
||||
"""Symlinks all files from the extension into extendee's install dir.
|
||||
|
||||
|
|
|
@ -2011,8 +2011,8 @@ def satisfies(self, other, deps=True, strict=False, strict_deps=False):
|
|||
other = self._autospec(other)
|
||||
|
||||
# The only way to satisfy a concrete spec is to match its hash exactly.
|
||||
if other._concrete:
|
||||
return self._concrete and self.dag_hash() == other.dag_hash()
|
||||
if other.concrete:
|
||||
return self.concrete and self.dag_hash() == other.dag_hash()
|
||||
|
||||
# A concrete provider can satisfy a virtual dependency.
|
||||
if not self.virtual and other.virtual:
|
||||
|
|
|
@ -108,6 +108,13 @@ def test_inheritance_of_diretives():
|
|||
assert 'mpi' in s
|
||||
|
||||
|
||||
def test_dependency_extensions():
|
||||
s = Spec('extension2')
|
||||
s.concretize()
|
||||
deps = set(x.name for x in s.package.dependency_activations())
|
||||
assert deps == set(['extension1'])
|
||||
|
||||
|
||||
def test_import_class_from_package(builtin_mock):
|
||||
from spack.pkg.builtin.mock.mpich import Mpich # noqa
|
||||
|
||||
|
|
|
@ -287,6 +287,14 @@ def test_unsatisfiable_compiler_flag(self):
|
|||
# 'mpich' is concrete:
|
||||
check_unsatisfiable('mpich', 'mpich cppflags="-O3"', True)
|
||||
|
||||
def test_copy_satisfies_transitive(self):
|
||||
spec = Spec('dttop')
|
||||
spec.concretize()
|
||||
copy = spec.copy()
|
||||
for s in spec.traverse():
|
||||
assert s.satisfies(copy[s.name])
|
||||
assert copy[s.name].satisfies(s)
|
||||
|
||||
def test_unsatisfiable_compiler_flag_mismatch(self):
|
||||
# No matchi in specs
|
||||
check_unsatisfiable(
|
||||
|
|
39
var/spack/repos/builtin.mock/packages/extendee/package.py
Normal file
39
var/spack/repos/builtin.mock/packages/extendee/package.py
Normal file
|
@ -0,0 +1,39 @@
|
|||
##############################################################################
|
||||
# Copyright (c) 2013-2016, Lawrence Livermore National Security, LLC.
|
||||
# Produced at the Lawrence Livermore National Laboratory.
|
||||
#
|
||||
# This file is part of Spack.
|
||||
# Created by Todd Gamblin, tgamblin@llnl.gov, All rights reserved.
|
||||
# LLNL-CODE-647188
|
||||
#
|
||||
# For details, see https://github.com/llnl/spack
|
||||
# Please also see the LICENSE file for our notice and the LGPL.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License (as
|
||||
# published by the Free Software Foundation) version 2.1, February 1999.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and
|
||||
# conditions of the GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
##############################################################################
|
||||
from spack import *
|
||||
|
||||
|
||||
class Extendee(Package):
|
||||
"""A package with extensions"""
|
||||
|
||||
homepage = "http://www.example.com"
|
||||
url = "http://www.example.com/extendee-1.0.tar.gz"
|
||||
|
||||
extendable = True
|
||||
|
||||
version('1.0', 'hash-extendee-1.0')
|
||||
|
||||
def install(self, spec, prefix):
|
||||
pass
|
39
var/spack/repos/builtin.mock/packages/extension1/package.py
Normal file
39
var/spack/repos/builtin.mock/packages/extension1/package.py
Normal file
|
@ -0,0 +1,39 @@
|
|||
##############################################################################
|
||||
# Copyright (c) 2013-2016, Lawrence Livermore National Security, LLC.
|
||||
# Produced at the Lawrence Livermore National Laboratory.
|
||||
#
|
||||
# This file is part of Spack.
|
||||
# Created by Todd Gamblin, tgamblin@llnl.gov, All rights reserved.
|
||||
# LLNL-CODE-647188
|
||||
#
|
||||
# For details, see https://github.com/llnl/spack
|
||||
# Please also see the LICENSE file for our notice and the LGPL.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License (as
|
||||
# published by the Free Software Foundation) version 2.1, February 1999.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and
|
||||
# conditions of the GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
##############################################################################
|
||||
from spack import *
|
||||
|
||||
|
||||
class Extension1(Package):
|
||||
"""A package which extends another package"""
|
||||
|
||||
homepage = "http://www.example.com"
|
||||
url = "http://www.example.com/extension1-1.0.tar.gz"
|
||||
|
||||
extends('extendee')
|
||||
|
||||
version('1.0', 'hash-extension1-1.0')
|
||||
|
||||
def install(self, spec, prefix):
|
||||
pass
|
41
var/spack/repos/builtin.mock/packages/extension2/package.py
Normal file
41
var/spack/repos/builtin.mock/packages/extension2/package.py
Normal file
|
@ -0,0 +1,41 @@
|
|||
##############################################################################
|
||||
# Copyright (c) 2013-2016, Lawrence Livermore National Security, LLC.
|
||||
# Produced at the Lawrence Livermore National Laboratory.
|
||||
#
|
||||
# This file is part of Spack.
|
||||
# Created by Todd Gamblin, tgamblin@llnl.gov, All rights reserved.
|
||||
# LLNL-CODE-647188
|
||||
#
|
||||
# For details, see https://github.com/llnl/spack
|
||||
# Please also see the LICENSE file for our notice and the LGPL.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License (as
|
||||
# published by the Free Software Foundation) version 2.1, February 1999.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and
|
||||
# conditions of the GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
##############################################################################
|
||||
from spack import *
|
||||
|
||||
|
||||
class Extension2(Package):
|
||||
"""A package which extends another package. It also depends on another
|
||||
package which extends the same package."""
|
||||
|
||||
homepage = "http://www.example.com"
|
||||
url = "http://www.example.com/extension2-1.0.tar.gz"
|
||||
|
||||
extends('extendee')
|
||||
depends_on('extension1', type=('build', 'run'))
|
||||
|
||||
version('1.0', 'hash-extension2-1.0')
|
||||
|
||||
def install(self, spec, prefix):
|
||||
pass
|
Loading…
Reference in a new issue