summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTodd Gamblin <tgamblin@llnl.gov>2019-12-02 01:01:11 -0800
committerTodd Gamblin <tgamblin@llnl.gov>2019-12-18 21:10:31 -0800
commit531f370e0d3256202e1eb40dce669e8ae2ebb15a (patch)
tree160cf29072d9da92792fbf3ca0499f33908f7d56
parent81b147cc0af9205061b4197b682b3058ce185c08 (diff)
downloadspack-531f370e0d3256202e1eb40dce669e8ae2ebb15a.tar.gz
spack-531f370e0d3256202e1eb40dce669e8ae2ebb15a.tar.bz2
spack-531f370e0d3256202e1eb40dce669e8ae2ebb15a.tar.xz
spack-531f370e0d3256202e1eb40dce669e8ae2ebb15a.zip
possible_dependencies() now reports missing dependencies
- Add an optional argument so that `possible_dependencies()` will report missing dependencies. - Add a test to ensure it works. - Ignore missing dependencies in `possible_dependencies()` by default.
-rw-r--r--lib/spack/spack/package.py54
-rw-r--r--lib/spack/spack/test/package_class.py9
-rw-r--r--var/spack/repos/builtin.mock/packages/missing-dependency/package.py21
3 files changed, 69 insertions, 15 deletions
diff --git a/lib/spack/spack/package.py b/lib/spack/spack/package.py
index c6dc39954c..5128a1e17f 100644
--- a/lib/spack/spack/package.py
+++ b/lib/spack/spack/package.py
@@ -556,16 +556,19 @@ class PackageBase(with_metaclass(PackageMeta, PackageViewMixin, object)):
@classmethod
def possible_dependencies(
cls, transitive=True, expand_virtuals=True, deptype='all',
- visited=None):
+ visited=None, missing=None):
"""Return dict of possible dependencies of this package.
Args:
- transitive (bool): return all transitive dependencies if True,
- only direct dependencies if False.
- expand_virtuals (bool): expand virtual dependencies into all
- possible implementations.
- deptype (str or tuple): dependency types to consider
- visited (set): set of names of dependencies visited so far.
+ transitive (bool, optional): return all transitive dependencies if
+ True, only direct dependencies if False (default True)..
+ expand_virtuals (bool, optional): expand virtual dependencies into
+ all possible implementations (default True)
+ deptype (str or tuple, optional): dependency types to consider
+ visited (dicct, optional): dict of names of dependencies visited so
+ far, mapped to their immediate dependencies' names.
+ missing (dict, optional): dict to populate with packages and their
+ *missing* dependencies.
Returns:
(dict): dictionary mapping dependency names to *their*
@@ -576,7 +579,12 @@ class PackageBase(with_metaclass(PackageMeta, PackageViewMixin, object)):
*immediate* dependencies. If ``expand_virtuals`` is ``False``,
virtual package names wil be inserted as keys mapped to empty
sets of dependencies. Virtuals, if not expanded, are treated as
- though they have no immediate dependencies
+ though they have no immediate dependencies.
+
+ Missing dependencies by default are ignored, but if a
+ missing dict is provided, it will be populated with package names
+ mapped to any dependencies they have that are in no
+ repositories. This is only populated if transitive is True.
Note: the returned dict *includes* the package itself.
@@ -586,6 +594,9 @@ class PackageBase(with_metaclass(PackageMeta, PackageViewMixin, object)):
if visited is None:
visited = {cls.name: set()}
+ if missing is None:
+ missing = {cls.name: set()}
+
for name, conditions in cls.dependencies.items():
# check whether this dependency could be of the type asked for
types = [dep.type for cond, dep in conditions.items()]
@@ -609,12 +620,24 @@ class PackageBase(with_metaclass(PackageMeta, PackageViewMixin, object)):
# recursively traverse dependencies
for dep_name in dep_names:
- if dep_name not in visited:
- visited.setdefault(dep_name, set())
- if transitive:
- dep_cls = spack.repo.path.get_pkg_class(dep_name)
- dep_cls.possible_dependencies(
- transitive, expand_virtuals, deptype, visited)
+ if dep_name in visited:
+ continue
+
+ visited.setdefault(dep_name, set())
+
+ # skip the rest if not transitive
+ if not transitive:
+ continue
+
+ try:
+ dep_cls = spack.repo.path.get_pkg_class(dep_name)
+ except spack.repo.UnknownPackageError:
+ # log unknown packages
+ missing.setdefault(cls.name, set()).add(dep_name)
+ continue
+
+ dep_cls.possible_dependencies(
+ transitive, expand_virtuals, deptype, visited, missing)
return visited
@@ -2671,6 +2694,7 @@ def possible_dependencies(*pkg_or_spec, **kwargs):
transitive = kwargs.get('transitive', True)
expand_virtuals = kwargs.get('expand_virtuals', True)
deptype = kwargs.get('deptype', 'all')
+ missing = kwargs.get('missing')
packages = []
for pos in pkg_or_spec:
@@ -2686,7 +2710,7 @@ def possible_dependencies(*pkg_or_spec, **kwargs):
visited = {}
for pkg in packages:
pkg.possible_dependencies(
- transitive, expand_virtuals, deptype, visited)
+ transitive, expand_virtuals, deptype, visited, missing)
return visited
diff --git a/lib/spack/spack/test/package_class.py b/lib/spack/spack/test/package_class.py
index 521bd9d54a..25c9258759 100644
--- a/lib/spack/spack/test/package_class.py
+++ b/lib/spack/spack/test/package_class.py
@@ -47,6 +47,15 @@ def test_possible_dependencies(mock_packages, mpileaks_possible_deps):
}
+def test_possible_dependencies_missing(mock_packages):
+ md = spack.repo.get("missing-dependency")
+ missing = {}
+ md.possible_dependencies(transitive=True, missing=missing)
+ assert missing["missing-dependency"] == set([
+ "this-is-a-missing-dependency"
+ ])
+
+
def test_possible_dependencies_with_deptypes(mock_packages):
dtbuild1 = spack.repo.get('dtbuild1')
diff --git a/var/spack/repos/builtin.mock/packages/missing-dependency/package.py b/var/spack/repos/builtin.mock/packages/missing-dependency/package.py
new file mode 100644
index 0000000000..e40e1b2a8b
--- /dev/null
+++ b/var/spack/repos/builtin.mock/packages/missing-dependency/package.py
@@ -0,0 +1,21 @@
+# Copyright 2013-2019 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)
+
+from spack import *
+
+
+class MissingDependency(Package):
+ """Package with a dependency that does not exist."""
+
+ homepage = "http://www.example.com"
+ url = "http://www.example.com/missing-dependency-1.0.tar.gz"
+
+ version('1.0', '0123456789abcdef0123456789abcdef')
+
+ # intentionally missing to test possible_dependencies()
+ depends_on("this-is-a-missing-dependency")
+
+ # this one is a "real" mock dependency
+ depends_on("a")