tests: each mock package now has its own class (#16157)
Packages in Spack are classes, and we need to be able to execute class methods on mock packages. The previous design used instances of a single MockPackage class; this version gives each package its own class that can spider depenencies. This allows us to implement class methods like `possible_dependencies()` on mock packages. This design change moves mock package creation into the `MockPackageMultiRepo`, and mock packages now *must* be created from a repo. This is required for us to mock `possible_dependencies()`, which needs to be able to get dependency packages from the package repo. Changes include: * `MockPackage` is now `MockPackageBase` * `MockPackageBase` instances must now be created with `MockPackageMultiRepo.add_package()` * add `possible_dependencies()` method to `MockPackageBase` * refactor tests to use new code structure * move package mocking infrastructure into `spack.util.mock_package`, as it's becoming a more sophisticated class and it gets lots in `conftest.py`
This commit is contained in:
parent
433a0b243f
commit
c6ada206af
9 changed files with 279 additions and 153 deletions
|
@ -18,7 +18,7 @@
|
|||
import spack.paths as spack_paths
|
||||
import spack.repo as repo
|
||||
from spack.spec import Spec
|
||||
from spack.test.conftest import MockPackage, MockPackageMultiRepo
|
||||
from spack.util.mock_package import MockPackageMultiRepo
|
||||
import spack.util.executable as exe
|
||||
import spack.util.spack_yaml as syaml
|
||||
import spack.util.gpg
|
||||
|
@ -101,15 +101,14 @@ def test_specs_staging(config):
|
|||
"""
|
||||
default = ('build', 'link')
|
||||
|
||||
g = MockPackage('g', [], [])
|
||||
f = MockPackage('f', [], [])
|
||||
e = MockPackage('e', [], [])
|
||||
d = MockPackage('d', [f, g], [default, default])
|
||||
c = MockPackage('c', [], [])
|
||||
b = MockPackage('b', [d, e], [default, default])
|
||||
a = MockPackage('a', [b, c], [default, default])
|
||||
|
||||
mock_repo = MockPackageMultiRepo([a, b, c, d, e, f, g])
|
||||
mock_repo = MockPackageMultiRepo()
|
||||
g = mock_repo.add_package('g', [], [])
|
||||
f = mock_repo.add_package('f', [], [])
|
||||
e = mock_repo.add_package('e', [], [])
|
||||
d = mock_repo.add_package('d', [f, g], [default, default])
|
||||
c = mock_repo.add_package('c', [], [])
|
||||
b = mock_repo.add_package('b', [d, e], [default, default])
|
||||
mock_repo.add_package('a', [b, c], [default, default])
|
||||
|
||||
with repo.swap(mock_repo):
|
||||
spec_a = Spec('a')
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
from spack.stage import stage_prefix
|
||||
|
||||
from spack.spec_list import SpecListError
|
||||
from spack.test.conftest import MockPackage, MockPackageMultiRepo
|
||||
from spack.util.mock_package import MockPackageMultiRepo
|
||||
import spack.util.spack_json as sjson
|
||||
|
||||
|
||||
|
@ -733,10 +733,10 @@ def create_v1_lockfile_dict(roots, all_specs):
|
|||
def test_read_old_lock_and_write_new(tmpdir):
|
||||
build_only = ('build',)
|
||||
|
||||
y = MockPackage('y', [], [])
|
||||
x = MockPackage('x', [y], [build_only])
|
||||
mock_repo = MockPackageMultiRepo()
|
||||
y = mock_repo.add_package('y', [], [])
|
||||
mock_repo.add_package('x', [y], [build_only])
|
||||
|
||||
mock_repo = MockPackageMultiRepo([x, y])
|
||||
with spack.repo.swap(mock_repo):
|
||||
x = Spec('x')
|
||||
x.concretize()
|
||||
|
@ -765,9 +765,9 @@ def test_read_old_lock_creates_backup(tmpdir):
|
|||
"""When reading a version-1 lockfile, make sure that a backup of that file
|
||||
is created.
|
||||
"""
|
||||
y = MockPackage('y', [], [])
|
||||
mock_repo = MockPackageMultiRepo()
|
||||
y = mock_repo.add_package('y', [], [])
|
||||
|
||||
mock_repo = MockPackageMultiRepo([y])
|
||||
with spack.repo.swap(mock_repo):
|
||||
y = Spec('y')
|
||||
y.concretize()
|
||||
|
@ -796,11 +796,10 @@ def test_indirect_build_dep():
|
|||
default = ('build', 'link')
|
||||
build_only = ('build',)
|
||||
|
||||
z = MockPackage('z', [], [])
|
||||
y = MockPackage('y', [z], [build_only])
|
||||
x = MockPackage('x', [y], [default])
|
||||
|
||||
mock_repo = MockPackageMultiRepo([x, y, z])
|
||||
mock_repo = MockPackageMultiRepo()
|
||||
z = mock_repo.add_package('z', [], [])
|
||||
y = mock_repo.add_package('y', [z], [build_only])
|
||||
mock_repo.add_package('x', [y], [default])
|
||||
|
||||
def noop(*args):
|
||||
pass
|
||||
|
@ -838,11 +837,10 @@ def test_store_different_build_deps():
|
|||
default = ('build', 'link')
|
||||
build_only = ('build',)
|
||||
|
||||
z = MockPackage('z', [], [])
|
||||
y = MockPackage('y', [z], [build_only])
|
||||
x = MockPackage('x', [y, z], [default, build_only])
|
||||
|
||||
mock_repo = MockPackageMultiRepo([x, y, z])
|
||||
mock_repo = MockPackageMultiRepo()
|
||||
z = mock_repo.add_package('z', [], [])
|
||||
y = mock_repo.add_package('y', [z], [build_only])
|
||||
mock_repo.add_package('x', [y, z], [default, build_only])
|
||||
|
||||
def noop(*args):
|
||||
pass
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
from spack.package_prefs import PackagePrefs
|
||||
from spack.spec import Spec, CompilerSpec, ConflictsInSpecError
|
||||
from spack.version import ver
|
||||
from spack.test.conftest import MockPackage, MockPackageMultiRepo
|
||||
from spack.util.mock_package import MockPackageMultiRepo
|
||||
import spack.compilers
|
||||
import spack.platforms.test
|
||||
|
||||
|
@ -235,10 +235,10 @@ def test_architecture_deep_inheritance(self):
|
|||
"""
|
||||
default_dep = ('link', 'build')
|
||||
|
||||
bazpkg = MockPackage('bazpkg', [], [])
|
||||
barpkg = MockPackage('barpkg', [bazpkg], [default_dep])
|
||||
foopkg = MockPackage('foopkg', [barpkg], [default_dep])
|
||||
mock_repo = MockPackageMultiRepo([foopkg, barpkg, bazpkg])
|
||||
mock_repo = MockPackageMultiRepo()
|
||||
bazpkg = mock_repo.add_package('bazpkg', [], [])
|
||||
barpkg = mock_repo.add_package('barpkg', [bazpkg], [default_dep])
|
||||
mock_repo.add_package('foopkg', [barpkg], [default_dep])
|
||||
|
||||
with spack.repo.swap(mock_repo):
|
||||
spec = Spec('foopkg %clang@3.3 os=CNL target=footar' +
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
import tempfile
|
||||
import xml.etree.ElementTree
|
||||
|
||||
import ordereddict_backport
|
||||
import py
|
||||
import pytest
|
||||
import ruamel.yaml as yaml
|
||||
|
@ -38,11 +37,8 @@
|
|||
import spack.util.gpg
|
||||
|
||||
from spack.util.pattern import Bunch
|
||||
from spack.dependency import Dependency
|
||||
from spack.fetch_strategy import FetchStrategyComposite, URLFetchStrategy
|
||||
from spack.fetch_strategy import FetchError
|
||||
from spack.spec import Spec
|
||||
from spack.version import Version
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
@ -1004,75 +1000,6 @@ def installation_dir_with_headers(tmpdir_factory):
|
|||
return root
|
||||
|
||||
|
||||
##########
|
||||
# Mock packages
|
||||
##########
|
||||
|
||||
|
||||
class MockPackage(object):
|
||||
def __init__(self, name, dependencies, dependency_types, conditions=None,
|
||||
versions=None):
|
||||
self.name = name
|
||||
self.spec = None
|
||||
self.dependencies = ordereddict_backport.OrderedDict()
|
||||
self._installed_upstream = False
|
||||
|
||||
assert len(dependencies) == len(dependency_types)
|
||||
for dep, dtype in zip(dependencies, dependency_types):
|
||||
d = Dependency(self, Spec(dep.name), type=dtype)
|
||||
if not conditions or dep.name not in conditions:
|
||||
self.dependencies[dep.name] = {Spec(name): d}
|
||||
else:
|
||||
dep_conditions = conditions[dep.name]
|
||||
dep_conditions = dict(
|
||||
(Spec(x), Dependency(self, Spec(y), type=dtype))
|
||||
for x, y in dep_conditions.items())
|
||||
self.dependencies[dep.name] = dep_conditions
|
||||
|
||||
if versions:
|
||||
self.versions = versions
|
||||
else:
|
||||
versions = list(Version(x) for x in [1, 2, 3])
|
||||
self.versions = dict((x, {'preferred': False}) for x in versions)
|
||||
|
||||
self.variants = {}
|
||||
self.provided = {}
|
||||
self.conflicts = {}
|
||||
self.patches = {}
|
||||
|
||||
def provides(self, vname):
|
||||
return vname in self.provided
|
||||
|
||||
@property
|
||||
def virtuals_provided(self):
|
||||
return [v.name for v, c in self.provided]
|
||||
|
||||
|
||||
class MockPackageMultiRepo(object):
|
||||
def __init__(self, packages):
|
||||
self.spec_to_pkg = dict((x.name, x) for x in packages)
|
||||
self.spec_to_pkg.update(
|
||||
dict(('mockrepo.' + x.name, x) for x in packages))
|
||||
|
||||
def get(self, spec):
|
||||
if not isinstance(spec, spack.spec.Spec):
|
||||
spec = Spec(spec)
|
||||
return self.spec_to_pkg[spec.name]
|
||||
|
||||
def get_pkg_class(self, name):
|
||||
return self.spec_to_pkg[name]
|
||||
|
||||
def exists(self, name):
|
||||
return name in self.spec_to_pkg
|
||||
|
||||
def is_virtual(self, name):
|
||||
return False
|
||||
|
||||
def repo_for_pkg(self, name):
|
||||
import collections
|
||||
Repo = collections.namedtuple('Repo', ['namespace'])
|
||||
return Repo('mockrepo')
|
||||
|
||||
##########
|
||||
# Specs of various kind
|
||||
##########
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
import spack.database
|
||||
import spack.package
|
||||
import spack.spec
|
||||
from spack.test.conftest import MockPackage, MockPackageMultiRepo
|
||||
from spack.util.mock_package import MockPackageMultiRepo
|
||||
from spack.util.executable import Executable
|
||||
|
||||
|
||||
|
@ -73,11 +73,11 @@ def test_installed_upstream(upstream_and_downstream_db):
|
|||
downstream_db, downstream_layout = (upstream_and_downstream_db)
|
||||
|
||||
default = ('build', 'link')
|
||||
x = MockPackage('x', [], [])
|
||||
z = MockPackage('z', [], [])
|
||||
y = MockPackage('y', [z], [default])
|
||||
w = MockPackage('w', [x, y], [default, default])
|
||||
mock_repo = MockPackageMultiRepo([w, x, y, z])
|
||||
mock_repo = MockPackageMultiRepo()
|
||||
x = mock_repo.add_package('x', [], [])
|
||||
z = mock_repo.add_package('z', [], [])
|
||||
y = mock_repo.add_package('y', [z], [default])
|
||||
mock_repo.add_package('w', [x, y], [default, default])
|
||||
|
||||
with spack.repo.swap(mock_repo):
|
||||
spec = spack.spec.Spec('w')
|
||||
|
@ -116,9 +116,9 @@ def test_removed_upstream_dep(upstream_and_downstream_db):
|
|||
downstream_db, downstream_layout = (upstream_and_downstream_db)
|
||||
|
||||
default = ('build', 'link')
|
||||
z = MockPackage('z', [], [])
|
||||
y = MockPackage('y', [z], [default])
|
||||
mock_repo = MockPackageMultiRepo([y, z])
|
||||
mock_repo = MockPackageMultiRepo()
|
||||
z = mock_repo.add_package('z', [], [])
|
||||
mock_repo.add_package('y', [z], [default])
|
||||
|
||||
with spack.repo.swap(mock_repo):
|
||||
spec = spack.spec.Spec('y')
|
||||
|
@ -150,8 +150,8 @@ def test_add_to_upstream_after_downstream(upstream_and_downstream_db):
|
|||
upstream_write_db, upstream_db, upstream_layout,\
|
||||
downstream_db, downstream_layout = (upstream_and_downstream_db)
|
||||
|
||||
x = MockPackage('x', [], [])
|
||||
mock_repo = MockPackageMultiRepo([x])
|
||||
mock_repo = MockPackageMultiRepo()
|
||||
mock_repo.add_package('x', [], [])
|
||||
|
||||
with spack.repo.swap(mock_repo):
|
||||
spec = spack.spec.Spec('x')
|
||||
|
@ -183,8 +183,8 @@ def test_cannot_write_upstream(tmpdir_factory, test_store, gen_mock_layout):
|
|||
roots = [str(tmpdir_factory.mktemp(x)) for x in ['a', 'b']]
|
||||
layouts = [gen_mock_layout(x) for x in ['/ra/', '/rb/']]
|
||||
|
||||
x = MockPackage('x', [], [])
|
||||
mock_repo = MockPackageMultiRepo([x])
|
||||
mock_repo = MockPackageMultiRepo()
|
||||
mock_repo.add_package('x', [], [])
|
||||
|
||||
# Instantiate the database that will be used as the upstream DB and make
|
||||
# sure it has an index file
|
||||
|
@ -209,11 +209,10 @@ def test_recursive_upstream_dbs(tmpdir_factory, test_store, gen_mock_layout):
|
|||
layouts = [gen_mock_layout(x) for x in ['/ra/', '/rb/', '/rc/']]
|
||||
|
||||
default = ('build', 'link')
|
||||
z = MockPackage('z', [], [])
|
||||
y = MockPackage('y', [z], [default])
|
||||
x = MockPackage('x', [y], [default])
|
||||
|
||||
mock_repo = MockPackageMultiRepo([x, y, z])
|
||||
mock_repo = MockPackageMultiRepo()
|
||||
z = mock_repo.add_package('z', [], [])
|
||||
y = mock_repo.add_package('y', [z], [default])
|
||||
mock_repo.add_package('x', [y], [default])
|
||||
|
||||
with spack.repo.swap(mock_repo):
|
||||
spec = spack.spec.Spec('x')
|
||||
|
@ -675,7 +674,7 @@ def test_115_reindex_with_packages_not_in_repo(mutable_database):
|
|||
# Dont add any package definitions to this repository, the idea is that
|
||||
# packages should not have to be defined in the repository once they
|
||||
# are installed
|
||||
with spack.repo.swap(MockPackageMultiRepo([])):
|
||||
with spack.repo.swap(MockPackageMultiRepo()):
|
||||
spack.store.store.reindex()
|
||||
_check_db_sanity(mutable_database)
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
from spack.spec import Spec
|
||||
from spack.dependency import all_deptypes, Dependency, canonical_deptype
|
||||
from spack.test.conftest import MockPackage, MockPackageMultiRepo
|
||||
from spack.util.mock_package import MockPackageMultiRepo
|
||||
|
||||
|
||||
def check_links(spec_to_check):
|
||||
|
@ -69,12 +69,12 @@ def test_test_deptype():
|
|||
default = ('build', 'link')
|
||||
test_only = ('test',)
|
||||
|
||||
x = MockPackage('x', [], [])
|
||||
z = MockPackage('z', [], [])
|
||||
y = MockPackage('y', [z], [test_only])
|
||||
w = MockPackage('w', [x, y], [test_only, default])
|
||||
mock_repo = MockPackageMultiRepo()
|
||||
x = mock_repo.add_package('x', [], [])
|
||||
z = mock_repo.add_package('z', [], [])
|
||||
y = mock_repo.add_package('y', [z], [test_only])
|
||||
w = mock_repo.add_package('w', [x, y], [test_only, default])
|
||||
|
||||
mock_repo = MockPackageMultiRepo([w, x, y, z])
|
||||
with spack.repo.swap(mock_repo):
|
||||
spec = Spec('w')
|
||||
spec.concretize(tests=(w.name,))
|
||||
|
@ -93,8 +93,9 @@ def test_installed_deps():
|
|||
default = ('build', 'link')
|
||||
build_only = ('build',)
|
||||
|
||||
e = MockPackage('e', [], [])
|
||||
d = MockPackage('d', [], [])
|
||||
mock_repo = MockPackageMultiRepo()
|
||||
e = mock_repo.add_package('e', [], [])
|
||||
d = mock_repo.add_package('d', [], [])
|
||||
c_conditions = {
|
||||
d.name: {
|
||||
'c': 'd@2'
|
||||
|
@ -103,11 +104,10 @@ def test_installed_deps():
|
|||
'c': 'e@2'
|
||||
}
|
||||
}
|
||||
c = MockPackage('c', [d, e], [build_only, default],
|
||||
c = mock_repo.add_package('c', [d, e], [build_only, default],
|
||||
conditions=c_conditions)
|
||||
b = MockPackage('b', [d, e], [default, default])
|
||||
a = MockPackage('a', [b, c], [default, default])
|
||||
mock_repo = MockPackageMultiRepo([a, b, c, d, e])
|
||||
b = mock_repo.add_package('b', [d, e], [default, default])
|
||||
mock_repo.add_package('a', [b, c], [default, default])
|
||||
|
||||
with spack.repo.swap(mock_repo):
|
||||
c_spec = Spec('c')
|
||||
|
@ -133,10 +133,10 @@ def test_specify_preinstalled_dep():
|
|||
"""
|
||||
default = ('build', 'link')
|
||||
|
||||
c = MockPackage('c', [], [])
|
||||
b = MockPackage('b', [c], [default])
|
||||
a = MockPackage('a', [b], [default])
|
||||
mock_repo = MockPackageMultiRepo([a, b, c])
|
||||
mock_repo = MockPackageMultiRepo()
|
||||
c = mock_repo.add_package('c', [], [])
|
||||
b = mock_repo.add_package('b', [c], [default])
|
||||
mock_repo.add_package('a', [b], [default])
|
||||
|
||||
with spack.repo.swap(mock_repo):
|
||||
b_spec = Spec('b')
|
||||
|
@ -161,15 +161,15 @@ def test_conditional_dep_with_user_constraints():
|
|||
"""
|
||||
default = ('build', 'link')
|
||||
|
||||
y = MockPackage('y', [], [])
|
||||
mock_repo = MockPackageMultiRepo()
|
||||
y = mock_repo.add_package('y', [], [])
|
||||
x_on_y_conditions = {
|
||||
y.name: {
|
||||
'x@2:': 'y'
|
||||
}
|
||||
}
|
||||
x = MockPackage('x', [y], [default], conditions=x_on_y_conditions)
|
||||
mock_repo.add_package('x', [y], [default], conditions=x_on_y_conditions)
|
||||
|
||||
mock_repo = MockPackageMultiRepo([x, y])
|
||||
with spack.repo.swap(mock_repo):
|
||||
spec = Spec('x ^y@2')
|
||||
spec.concretize()
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
from spack import repo
|
||||
from spack.spec import Spec, save_dependency_spec_yamls
|
||||
from spack.util.spack_yaml import syaml_dict
|
||||
from spack.test.conftest import MockPackage, MockPackageMultiRepo
|
||||
from spack.util.mock_package import MockPackageMultiRepo
|
||||
|
||||
|
||||
def check_yaml_round_trip(spec):
|
||||
|
@ -301,15 +301,14 @@ def test_save_dependency_spec_yamls_subset(tmpdir, config):
|
|||
|
||||
default = ('build', 'link')
|
||||
|
||||
g = MockPackage('g', [], [])
|
||||
f = MockPackage('f', [], [])
|
||||
e = MockPackage('e', [], [])
|
||||
d = MockPackage('d', [f, g], [default, default])
|
||||
c = MockPackage('c', [], [])
|
||||
b = MockPackage('b', [d, e], [default, default])
|
||||
a = MockPackage('a', [b, c], [default, default])
|
||||
|
||||
mock_repo = MockPackageMultiRepo([a, b, c, d, e, f, g])
|
||||
mock_repo = MockPackageMultiRepo()
|
||||
g = mock_repo.add_package('g', [], [])
|
||||
f = mock_repo.add_package('f', [], [])
|
||||
e = mock_repo.add_package('e', [], [])
|
||||
d = mock_repo.add_package('d', [f, g], [default, default])
|
||||
c = mock_repo.add_package('c', [], [])
|
||||
b = mock_repo.add_package('b', [d, e], [default, default])
|
||||
mock_repo.add_package('a', [b, c], [default, default])
|
||||
|
||||
with repo.swap(mock_repo):
|
||||
spec_a = Spec('a')
|
||||
|
|
43
lib/spack/spack/test/util/mock_package.py
Normal file
43
lib/spack/spack/test/util/mock_package.py
Normal file
|
@ -0,0 +1,43 @@
|
|||
# Copyright 2013-2020 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)
|
||||
|
||||
import spack.repo
|
||||
from spack.util.mock_package import MockPackageMultiRepo
|
||||
|
||||
|
||||
def test_mock_package_possible_dependencies():
|
||||
mock_repo = MockPackageMultiRepo()
|
||||
e = mock_repo.add_package('e')
|
||||
d = mock_repo.add_package('d', [e])
|
||||
c = mock_repo.add_package('c', [d])
|
||||
b = mock_repo.add_package('b', [d])
|
||||
a = mock_repo.add_package('a', [b, c])
|
||||
|
||||
with spack.repo.swap(mock_repo):
|
||||
assert set(a.possible_dependencies()) == set(['a', 'b', 'c', 'd', 'e'])
|
||||
assert set(b.possible_dependencies()) == set(['b', 'd', 'e'])
|
||||
assert set(c.possible_dependencies()) == set(['c', 'd', 'e'])
|
||||
assert set(d.possible_dependencies()) == set(['d', 'e'])
|
||||
assert set(e.possible_dependencies()) == set(['e'])
|
||||
|
||||
assert set(
|
||||
a.possible_dependencies(transitive=False)) == set(['a', 'b', 'c'])
|
||||
assert set(
|
||||
b.possible_dependencies(transitive=False)) == set(['b', 'd'])
|
||||
assert set(
|
||||
c.possible_dependencies(transitive=False)) == set(['c', 'd'])
|
||||
assert set(
|
||||
d.possible_dependencies(transitive=False)) == set(['d', 'e'])
|
||||
assert set(
|
||||
e.possible_dependencies(transitive=False)) == set(['e'])
|
||||
|
||||
|
||||
def test_mock_repo_is_virtual():
|
||||
mock_repo = MockPackageMultiRepo()
|
||||
|
||||
# current implementation is always false
|
||||
assert mock_repo.is_virtual("foo") is False
|
||||
assert mock_repo.is_virtual("bar") is False
|
||||
assert mock_repo.is_virtual("baz") is False
|
161
lib/spack/spack/util/mock_package.py
Normal file
161
lib/spack/spack/util/mock_package.py
Normal file
|
@ -0,0 +1,161 @@
|
|||
# Copyright 2013-2020 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)
|
||||
|
||||
"""Infrastructure used by tests for mocking packages and repos."""
|
||||
|
||||
import ordereddict_backport
|
||||
|
||||
import spack.util.naming
|
||||
from spack.dependency import Dependency
|
||||
from spack.spec import Spec
|
||||
from spack.version import Version
|
||||
|
||||
__all__ = ["MockPackageMultiRepo"]
|
||||
|
||||
|
||||
class MockPackageBase(object):
|
||||
"""Internal base class for mocking ``spack.package.PackageBase``.
|
||||
|
||||
Use ``MockPackageMultiRepo.add_package()`` to create new instances.
|
||||
|
||||
"""
|
||||
def __init__(self, dependencies, dependency_types,
|
||||
conditions=None, versions=None):
|
||||
"""Instantiate a new MockPackageBase.
|
||||
|
||||
This is not for general use; it needs to be constructed by a
|
||||
``MockPackageMultiRepo``, as we need to know about *all* packages
|
||||
to find possible depenencies.
|
||||
|
||||
"""
|
||||
self.spec = None
|
||||
self._installed_upstream = False
|
||||
|
||||
def provides(self, vname):
|
||||
return vname in self.provided
|
||||
|
||||
@property
|
||||
def virtuals_provided(self):
|
||||
return [v.name for v, c in self.provided]
|
||||
|
||||
@classmethod
|
||||
def possible_dependencies(
|
||||
cls, transitive=True, deptype='all', visited=None, virtuals=None):
|
||||
visited = {} if visited is None else visited
|
||||
|
||||
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()]
|
||||
types = set.union(*types)
|
||||
if not any(d in types for d in deptype):
|
||||
continue
|
||||
|
||||
visited.setdefault(cls.name, set())
|
||||
for dep_name in cls.dependencies:
|
||||
if dep_name in visited:
|
||||
continue
|
||||
|
||||
visited.setdefault(dep_name, set())
|
||||
|
||||
if not transitive:
|
||||
continue
|
||||
|
||||
cls._repo.get(dep_name).possible_dependencies(
|
||||
transitive, deptype, visited, virtuals)
|
||||
|
||||
return visited
|
||||
|
||||
|
||||
class MockPackageMultiRepo(object):
|
||||
"""Mock package repository, mimicking ``spack.repo.Repo``."""
|
||||
|
||||
def __init__(self):
|
||||
self.spec_to_pkg = {}
|
||||
|
||||
def get(self, spec):
|
||||
if not isinstance(spec, spack.spec.Spec):
|
||||
spec = Spec(spec)
|
||||
return self.spec_to_pkg[spec.name]
|
||||
|
||||
def get_pkg_class(self, name):
|
||||
return self.spec_to_pkg[name]
|
||||
|
||||
def exists(self, name):
|
||||
return name in self.spec_to_pkg
|
||||
|
||||
def is_virtual(self, name):
|
||||
return False
|
||||
|
||||
def repo_for_pkg(self, name):
|
||||
import collections
|
||||
Repo = collections.namedtuple('Repo', ['namespace'])
|
||||
return Repo('mockrepo')
|
||||
|
||||
def add_package(self, name, dependencies=None, dependency_types=None,
|
||||
conditions=None):
|
||||
"""Factory method for creating mock packages.
|
||||
|
||||
This creates a new subclass of ``MockPackageBase``, ensures that its
|
||||
``name`` and ``__name__`` properties are set up correctly, and
|
||||
returns a new instance.
|
||||
|
||||
We use a factory function here because many functions and properties
|
||||
of packages need to be class functions.
|
||||
|
||||
Args:
|
||||
name (str): name of the new package
|
||||
dependencies (list): list of mock packages to be dependencies
|
||||
for this new package (optional; no deps if not provided)
|
||||
dependency_type (list): list of deptypes for each dependency
|
||||
(optional; will be default_deptype if not provided)
|
||||
conditions (list): condition specs for each dependency (optional)
|
||||
|
||||
"""
|
||||
if not dependencies:
|
||||
dependencies = []
|
||||
|
||||
if not dependency_types:
|
||||
dependency_types = [
|
||||
spack.dependency.default_deptype] * len(dependencies)
|
||||
|
||||
assert len(dependencies) == len(dependency_types)
|
||||
|
||||
# new class for the mock package
|
||||
class MockPackage(MockPackageBase):
|
||||
pass
|
||||
MockPackage.__name__ = spack.util.naming.mod_to_class(name)
|
||||
MockPackage.name = name
|
||||
MockPackage._repo = self
|
||||
|
||||
# set up dependencies
|
||||
MockPackage.dependencies = ordereddict_backport.OrderedDict()
|
||||
for dep, dtype in zip(dependencies, dependency_types):
|
||||
d = Dependency(MockPackage, Spec(dep.name), type=dtype)
|
||||
if not conditions or dep.name not in conditions:
|
||||
MockPackage.dependencies[dep.name] = {Spec(name): d}
|
||||
else:
|
||||
dep_conditions = conditions[dep.name]
|
||||
dep_conditions = dict(
|
||||
(Spec(x), Dependency(MockPackage, Spec(y), type=dtype))
|
||||
for x, y in dep_conditions.items())
|
||||
MockPackage.dependencies[dep.name] = dep_conditions
|
||||
|
||||
# each package has some fake versions
|
||||
versions = list(Version(x) for x in [1, 2, 3])
|
||||
MockPackage.versions = dict(
|
||||
(x, {'preferred': False}) for x in versions
|
||||
)
|
||||
|
||||
MockPackage.variants = {}
|
||||
MockPackage.provided = {}
|
||||
MockPackage.conflicts = {}
|
||||
MockPackage.patches = {}
|
||||
|
||||
mock_package = MockPackage(
|
||||
dependencies, dependency_types, conditions, versions)
|
||||
self.spec_to_pkg[name] = mock_package
|
||||
self.spec_to_pkg["mockrepo." + name] = mock_package
|
||||
|
||||
return mock_package
|
Loading…
Reference in a new issue