repo: generalize "swap" context manager to also accept paths

The method is now called "use_repositories" and
makes it clear in the docstring that it accepts
as arguments either Repo objects or paths.

Since there was some duplication between this
contextmanager and "use_repo" in the testing framework,
remove the latter and use spack.repo.use_repositories
across the entire code base.

Make a few adjustment to MockPackageMultiRepo, since it was
stating in the docstring that it was supposed to mock
spack.repo.Repo and was instead mocking spack.repo.RepoPath.
This commit is contained in:
Massimiliano Culpo 2021-01-31 11:31:57 +01:00 committed by Todd Gamblin
parent 0007ed72c3
commit 1a8963b0f4
16 changed files with 71 additions and 61 deletions

View File

@ -1259,23 +1259,6 @@ def set_path(repo):
return append
@contextlib.contextmanager
def swap(repo_path):
"""Temporarily use another RepoPath."""
global path
# swap out _path for repo_path
saved = path
remove_from_meta = set_path(repo_path)
yield
# restore _path and sys.meta_path
if remove_from_meta:
sys.meta_path.remove(repo_path)
path = saved
@contextlib.contextmanager
def additional_repository(repository):
"""Adds temporarily a repository to the default one.
@ -1288,6 +1271,34 @@ def additional_repository(repository):
path.remove(repository)
@contextlib.contextmanager
def use_repositories(*paths_and_repos):
"""Use the repositories passed as arguments within the context manager.
Args:
*paths_and_repos: paths to the repositories to be used, or
already constructed Repo objects
Returns:
Corresponding RepoPath object
"""
global path
# Construct a temporary RepoPath object from
temporary_repositories = RepoPath(*paths_and_repos)
# Swap the current repository out
saved = path
remove_from_meta = set_path(temporary_repositories)
yield temporary_repositories
# Restore _path and sys.meta_path
if remove_from_meta:
sys.meta_path.remove(temporary_repositories)
path = saved
class RepoError(spack.error.SpackError):
"""Superclass for repository-related errors."""

View File

@ -73,7 +73,7 @@ def test_specs_staging(config):
b = mock_repo.add_package('b', [d, e], [default, default])
mock_repo.add_package('a', [b, c], [default, default])
with repo.swap(mock_repo):
with repo.use_repositories(mock_repo):
spec_a = Spec('a')
spec_a.concretize()

View File

@ -330,7 +330,7 @@ def test_env_status_broken_view(
# switch to a new repo that doesn't include the installed package
# test that Spack detects the missing package and warns the user
new_repo = MockPackageMultiRepo()
with spack.repo.swap(new_repo):
with spack.repo.use_repositories(new_repo):
output = env('status')
assert 'In environment test' in output
assert 'Environment test includes out of date' in output
@ -351,7 +351,7 @@ def test_env_activate_broken_view(
# switch to a new repo that doesn't include the installed package
# test that Spack detects the missing package and fails gracefully
new_repo = MockPackageMultiRepo()
with spack.repo.swap(new_repo):
with spack.repo.use_repositories(new_repo):
with pytest.raises(SpackCommandError):
env('activate', '--sh', 'test')
@ -929,7 +929,7 @@ def test_read_old_lock_and_write_new(tmpdir):
y = mock_repo.add_package('y', [], [])
mock_repo.add_package('x', [y], [build_only])
with spack.repo.swap(mock_repo):
with spack.repo.use_repositories(mock_repo):
x = Spec('x')
x.concretize()
@ -960,7 +960,7 @@ def test_read_old_lock_creates_backup(tmpdir):
mock_repo = MockPackageMultiRepo()
y = mock_repo.add_package('y', [], [])
with spack.repo.swap(mock_repo):
with spack.repo.use_repositories(mock_repo):
y = Spec('y')
y.concretize()
@ -997,7 +997,7 @@ def noop(*args):
pass
setattr(mock_repo, 'dump_provenance', noop)
with spack.repo.swap(mock_repo):
with spack.repo.use_repositories(mock_repo):
x_spec = Spec('x')
x_concretized = x_spec.concretized()
@ -1038,7 +1038,7 @@ def noop(*args):
pass
setattr(mock_repo, 'dump_provenance', noop)
with spack.repo.swap(mock_repo):
with spack.repo.use_repositories(mock_repo):
y_spec = Spec('y ^z@3')
y_concretized = y_spec.concretized()

View File

@ -10,7 +10,7 @@
import spack.main
import spack.modules
from spack.test.conftest import use_store, use_configuration, use_repo
from spack.test.conftest import use_store, use_configuration
module = spack.main.SpackCommand('module')
@ -23,7 +23,7 @@ def ensure_module_files_are_there(
module = spack.main.SpackCommand('module')
with use_store(mock_store):
with use_configuration(mock_configuration):
with use_repo(mock_repo_path):
with spack.repo.use_repositories(mock_repo_path):
module('tcl', 'refresh', '-y')

View File

@ -82,7 +82,7 @@ def mock_pkg_git_repo(tmpdir_factory):
git('-c', 'commit.gpgsign=false', 'commit',
'-m', 'change pkg-b, remove pkg-c, add pkg-d')
with spack.repo.swap(mock_repo):
with spack.repo.use_repositories(mock_repo):
yield mock_repo_packages

View File

@ -304,7 +304,7 @@ def test_architecture_deep_inheritance(self, mock_targets):
barpkg = mock_repo.add_package('barpkg', [bazpkg], [default_dep])
mock_repo.add_package('foopkg', [barpkg], [default_dep])
with spack.repo.swap(mock_repo):
with spack.repo.use_repositories(mock_repo):
spec = Spec('foopkg %gcc@4.5.0 os=CNL target=nocona' +
' ^barpkg os=SuSE11 ^bazpkg os=be')
spec.concretize()

View File

@ -382,19 +382,12 @@ def use_store(store):
spack.store.store = saved
@contextlib.contextmanager
def use_repo(repo):
"""Context manager to swap out the global Spack repo path."""
with spack.repo.swap(repo):
yield
#
# Test-specific fixtures
#
@pytest.fixture(scope='session')
def mock_repo_path():
yield spack.repo.RepoPath(spack.paths.mock_packages_path)
yield spack.repo.Repo(spack.paths.mock_packages_path)
def _pkg_install_fn(pkg, spec, prefix):
@ -411,15 +404,15 @@ def mock_pkg_install(monkeypatch):
@pytest.fixture(scope='function')
def mock_packages(mock_repo_path, mock_pkg_install):
"""Use the 'builtin.mock' repository instead of 'builtin'"""
with use_repo(mock_repo_path):
yield mock_repo_path
with spack.repo.use_repositories(mock_repo_path) as mock_repo:
yield mock_repo
@pytest.fixture(scope='function')
def mutable_mock_repo(mock_repo_path):
"""Function-scoped mock packages, for tests that need to modify them."""
mock_repo_path = spack.repo.RepoPath(spack.paths.mock_packages_path)
with use_repo(mock_repo_path):
mock_repo = spack.repo.Repo(spack.paths.mock_packages_path)
with spack.repo.use_repositories(mock_repo) as mock_repo_path:
yield mock_repo_path
@ -643,7 +636,7 @@ def mock_store(tmpdir_factory, mock_repo_path, mock_configuration,
if not os.path.exists(str(store_cache.join('.spack-db'))):
with use_configuration(mock_configuration):
with use_store(store):
with use_repo(mock_repo_path):
with spack.repo.use_repositories(mock_repo_path):
_populate(store.db)
store_path.copy(store_cache, mode=True, stat=True)
@ -673,7 +666,7 @@ def mutable_mock_store(tmpdir_factory, mock_repo_path, mock_configuration,
if not os.path.exists(str(store_cache.join('.spack-db'))):
with use_configuration(mock_configuration):
with use_store(store):
with use_repo(mock_repo_path):
with spack.repo.use_repositories(mock_repo_path):
_populate(store.db)
store_path.copy(store_cache, mode=True, stat=True)
@ -1249,8 +1242,7 @@ def mock_test_repo(tmpdir_factory):
namespace: mock_test_repo
""")
repo = spack.repo.RepoPath(str(repodir))
with spack.repo.swap(repo):
with spack.repo.use_repositories(str(repodir)) as repo:
yield repo, repodir
shutil.rmtree(str(repodir))

View File

@ -81,7 +81,7 @@ def test_installed_upstream(upstream_and_downstream_db):
y = mock_repo.add_package('y', [z], [default])
mock_repo.add_package('w', [x, y], [default, default])
with spack.repo.swap(mock_repo):
with spack.repo.use_repositories(mock_repo):
spec = spack.spec.Spec('w')
spec.concretize()
@ -122,7 +122,7 @@ def test_removed_upstream_dep(upstream_and_downstream_db):
z = mock_repo.add_package('z', [], [])
mock_repo.add_package('y', [z], [default])
with spack.repo.swap(mock_repo):
with spack.repo.use_repositories(mock_repo):
spec = spack.spec.Spec('y')
spec.concretize()
@ -155,7 +155,7 @@ def test_add_to_upstream_after_downstream(upstream_and_downstream_db):
mock_repo = MockPackageMultiRepo()
mock_repo.add_package('x', [], [])
with spack.repo.swap(mock_repo):
with spack.repo.use_repositories(mock_repo):
spec = spack.spec.Spec('x')
spec.concretize()
@ -197,7 +197,7 @@ def test_cannot_write_upstream(tmpdir_factory, test_store, gen_mock_layout):
upstream_dbs = spack.store._construct_upstream_dbs_from_install_roots(
[roots[1]], _test=True)
with spack.repo.swap(mock_repo):
with spack.repo.use_repositories(mock_repo):
spec = spack.spec.Spec('x')
spec.concretize()
@ -216,7 +216,7 @@ def test_recursive_upstream_dbs(tmpdir_factory, test_store, gen_mock_layout):
y = mock_repo.add_package('y', [z], [default])
mock_repo.add_package('x', [y], [default])
with spack.repo.swap(mock_repo):
with spack.repo.use_repositories(mock_repo):
spec = spack.spec.Spec('x')
spec.concretize()
db_c = spack.database.Database(roots[2])
@ -694,7 +694,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.use_repositories(MockPackageMultiRepo()):
spack.store.store.reindex()
_check_db_sanity(mutable_database)

View File

@ -194,7 +194,7 @@ def test_handle_unknown_package(layout_and_dir, config, mock_packages):
layout.create_install_directory(spec)
installed_specs[spec] = layout.path_for_spec(spec)
with spack.repo.swap(mock_db):
with spack.repo.use_repositories(mock_db):
# Now check that even without the package files, we know
# enough to read a spec from the spec file.
for spec, path in installed_specs.items():

View File

@ -474,14 +474,14 @@ def _conc_spec(compiler):
assert packages
def test_dump_packages_deps_ok(install_mockery, tmpdir, mock_repo_path):
def test_dump_packages_deps_ok(install_mockery, tmpdir, mock_packages):
"""Test happy path for dump_packages with dependencies."""
spec_name = 'simple-inheritance'
spec = spack.spec.Spec(spec_name).concretized()
inst.dump_packages(spec, str(tmpdir))
repo = mock_repo_path.repos[0]
repo = mock_packages.repos[0]
dest_pkg = repo.filename_for_package_name(spec_name)
assert os.path.isfile(dest_pkg)

View File

@ -73,7 +73,7 @@ def test_repo_getpkg_names_and_classes():
def test_get_all_mock_packages():
"""Get the mock packages once each too."""
db = spack.repo.RepoPath(spack.paths.mock_packages_path)
with spack.repo.swap(db):
with spack.repo.use_repositories(db):
check_repo()

View File

@ -75,7 +75,7 @@ def test_test_deptype():
y = mock_repo.add_package('y', [z], [test_only])
w = mock_repo.add_package('w', [x, y], [test_only, default])
with spack.repo.swap(mock_repo):
with spack.repo.use_repositories(mock_repo):
spec = Spec('w')
spec.concretize(tests=(w.name,))
@ -114,7 +114,7 @@ def test_installed_deps():
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):
with spack.repo.use_repositories(mock_repo):
c_spec = Spec('c')
c_spec.concretize()
assert c_spec['d'].version == spack.version.Version('2')
@ -143,7 +143,7 @@ def test_specify_preinstalled_dep():
b = mock_repo.add_package('b', [c], [default])
mock_repo.add_package('a', [b], [default])
with spack.repo.swap(mock_repo):
with spack.repo.use_repositories(mock_repo):
b_spec = Spec('b')
b_spec.concretize()
for spec in b_spec.traverse():
@ -186,7 +186,7 @@ def test_conditional_dep_with_user_constraints(spec_str, expr_str, expected):
}
mock_repo.add_package('x', [y], [default], conditions=x_on_y_conditions)
with spack.repo.swap(mock_repo):
with spack.repo.use_repositories(mock_repo):
spec = Spec(spec_str)
spec.concretize()

View File

@ -315,7 +315,7 @@ def test_save_dependency_spec_yamls_subset(tmpdir, config):
b = mock_repo.add_package('b', [d, e], [default, default])
mock_repo.add_package('a', [b, c], [default, default])
with repo.swap(mock_repo):
with repo.use_repositories(mock_repo):
spec_a = Spec('a')
spec_a.concretize()
b_spec = spec_a['b']

View File

@ -54,7 +54,7 @@ def builtin_and_mock_packages():
repo_dirs = [spack.paths.packages_path, spack.paths.mock_packages_path]
path = RepoPath(*repo_dirs)
with spack.repo.swap(path):
with spack.repo.use_repositories(path):
yield

View File

@ -15,7 +15,7 @@ def test_mock_package_possible_dependencies():
b = mock_repo.add_package('b', [d])
a = mock_repo.add_package('a', [b, c])
with spack.repo.swap(mock_repo):
with spack.repo.use_repositories(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'])

View File

@ -8,6 +8,7 @@
import ordereddict_backport
import spack.util.naming
import spack.provider_index
from spack.dependency import Dependency
from spack.spec import Spec
from spack.version import Version
@ -80,6 +81,8 @@ class MockPackageMultiRepo(object):
def __init__(self):
self.spec_to_pkg = {}
self.namespace = ''
self.full_namespace = 'spack.pkg.mock'
def get(self, spec):
if not isinstance(spec, spack.spec.Spec):
@ -171,3 +174,7 @@ class MockPackage(MockPackageBase):
self.spec_to_pkg["mockrepo." + name] = mock_package
return mock_package
@property
def provider_index(self):
return spack.provider_index.ProviderIndex()