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.

(cherry picked from commit 1a8963b0f4)
This commit is contained in:
Massimiliano Culpo 2021-01-31 11:31:57 +01:00
parent 2a4d2f905c
commit 0678d5df90
16 changed files with 71 additions and 61 deletions

View File

@ -1255,23 +1255,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.
@ -1284,6 +1267,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
@ -644,7 +637,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)
@ -674,7 +667,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)
@ -1250,8 +1243,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()