packages.yaml: allow virtuals to specify buildable: false (#14934)
Currently, to force Spack to use an external MPI, you have to specify `buildable: False` for every MPI provider in Spack in your packages.yaml file. This is both tedious and fragile, as new MPI providers can be added and break your workflow when you do a git pull. This PR allows you to specify an entire virtual dependency as non-buildable, and specify particular implementations to be built: ``` packages: all: providers: mpi: [mpich] mpi: buildable: false paths: mpich@3.2 %gcc@7.3.0: /usr/packages/mpich-3.2-gcc-7.3.0 ``` will force all Spack builds to use the specified `mpich` install.
This commit is contained in:
parent
8748160984
commit
336191c251
@ -124,6 +124,39 @@ The ``buildable`` does not need to be paired with external packages.
|
|||||||
It could also be used alone to forbid packages that may be
|
It could also be used alone to forbid packages that may be
|
||||||
buggy or otherwise undesirable.
|
buggy or otherwise undesirable.
|
||||||
|
|
||||||
|
Virtual packages in Spack can also be specified as not buildable, and
|
||||||
|
external implementations can be provided. In the example above,
|
||||||
|
OpenMPI is configured as not buildable, but Spack will often prefer
|
||||||
|
other MPI implementations over the externally available OpenMPI. Spack
|
||||||
|
can be configured with every MPI provider not buildable individually,
|
||||||
|
but more conveniently:
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
packages:
|
||||||
|
mpi:
|
||||||
|
buildable: False
|
||||||
|
openmpi:
|
||||||
|
paths:
|
||||||
|
openmpi@1.4.3%gcc@4.4.7 arch=linux-debian7-x86_64: /opt/openmpi-1.4.3
|
||||||
|
openmpi@1.4.3%gcc@4.4.7 arch=linux-debian7-x86_64+debug: /opt/openmpi-1.4.3-debug
|
||||||
|
openmpi@1.6.5%intel@10.1 arch=linux-debian7-x86_64: /opt/openmpi-1.6.5-intel
|
||||||
|
|
||||||
|
Implementations can also be listed immediately under the virtual they provide:
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
packages:
|
||||||
|
mpi:
|
||||||
|
buildable: False
|
||||||
|
openmpi@1.4.3%gcc@4.4.7 arch=linux-debian7-x86_64: /opt/openmpi-1.4.3
|
||||||
|
openmpi@1.4.3%gcc@4.4.7 arch=linux-debian7-x86_64+debug: /opt/openmpi-1.4.3-debug
|
||||||
|
openmpi@1.6.5%intel@10.1 arch=linux-debian7-x86_64: /opt/openmpi-1.6.5-intel
|
||||||
|
mpich@3.3 %clang@9.0.0 arch=linux-debian7-x86_64: /opt/mpich-3.3-intel
|
||||||
|
|
||||||
|
Spack can then use any of the listed external implementations of MPI
|
||||||
|
to satisfy a dependency, and will choose depending on the compiler and
|
||||||
|
architecture.
|
||||||
|
|
||||||
.. _concretization-preferences:
|
.. _concretization-preferences:
|
||||||
|
|
||||||
|
@ -1035,6 +1035,14 @@ def provides(self, vpkg_name):
|
|||||||
for s, constraints in self.provided.items() if s.name == vpkg_name
|
for s, constraints in self.provided.items() if s.name == vpkg_name
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def virtuals_provided(self):
|
||||||
|
"""
|
||||||
|
virtual packages provided by this package with its spec
|
||||||
|
"""
|
||||||
|
return [vspec for vspec, constraints in self.provided.items()
|
||||||
|
if any(self.spec.satisfies(c) for c in constraints)]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def installed(self):
|
def installed(self):
|
||||||
"""Installation status of a package.
|
"""Installation status of a package.
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
import stat
|
import stat
|
||||||
|
|
||||||
from six import string_types
|
from six import string_types
|
||||||
from six import iteritems
|
|
||||||
|
|
||||||
import spack.repo
|
import spack.repo
|
||||||
import spack.error
|
import spack.error
|
||||||
@ -23,27 +22,6 @@ def _spec_type(component):
|
|||||||
return _lesser_spec_types.get(component, spack.spec.Spec)
|
return _lesser_spec_types.get(component, spack.spec.Spec)
|
||||||
|
|
||||||
|
|
||||||
def get_packages_config():
|
|
||||||
"""Wrapper around get_packages_config() to validate semantics."""
|
|
||||||
config = spack.config.get('packages')
|
|
||||||
|
|
||||||
# Get a list of virtuals from packages.yaml. Note that because we
|
|
||||||
# check spack.repo, this collects virtuals that are actually provided
|
|
||||||
# by sometihng, not just packages/names that don't exist.
|
|
||||||
# So, this won't include, e.g., 'all'.
|
|
||||||
virtuals = [(pkg_name, pkg_name._start_mark) for pkg_name in config
|
|
||||||
if spack.repo.path.is_virtual(pkg_name)]
|
|
||||||
|
|
||||||
# die if there are virtuals in `packages.py`
|
|
||||||
if virtuals:
|
|
||||||
errors = ["%s: %s" % (line_info, name) for name, line_info in virtuals]
|
|
||||||
raise VirtualInPackagesYAMLError(
|
|
||||||
"packages.yaml entries cannot be virtual packages:",
|
|
||||||
'\n'.join(errors))
|
|
||||||
|
|
||||||
return config
|
|
||||||
|
|
||||||
|
|
||||||
class PackagePrefs(object):
|
class PackagePrefs(object):
|
||||||
"""Defines the sort order for a set of specs.
|
"""Defines the sort order for a set of specs.
|
||||||
|
|
||||||
@ -116,7 +94,7 @@ def order_for_package(cls, pkgname, component, vpkg=None, all=True):
|
|||||||
pkglist.append('all')
|
pkglist.append('all')
|
||||||
|
|
||||||
for pkg in pkglist:
|
for pkg in pkglist:
|
||||||
pkg_entry = get_packages_config().get(pkg)
|
pkg_entry = spack.config.get('packages').get(pkg)
|
||||||
if not pkg_entry:
|
if not pkg_entry:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@ -160,7 +138,8 @@ def has_preferred_targets(cls, pkg_name):
|
|||||||
def preferred_variants(cls, pkg_name):
|
def preferred_variants(cls, pkg_name):
|
||||||
"""Return a VariantMap of preferred variants/values for a spec."""
|
"""Return a VariantMap of preferred variants/values for a spec."""
|
||||||
for pkg in (pkg_name, 'all'):
|
for pkg in (pkg_name, 'all'):
|
||||||
variants = get_packages_config().get(pkg, {}).get('variants', '')
|
variants = spack.config.get('packages').get(pkg, {}).get(
|
||||||
|
'variants', '')
|
||||||
if variants:
|
if variants:
|
||||||
break
|
break
|
||||||
|
|
||||||
@ -181,33 +160,29 @@ def spec_externals(spec):
|
|||||||
# break circular import.
|
# break circular import.
|
||||||
from spack.util.module_cmd import get_path_from_module # NOQA: ignore=F401
|
from spack.util.module_cmd import get_path_from_module # NOQA: ignore=F401
|
||||||
|
|
||||||
allpkgs = get_packages_config()
|
allpkgs = spack.config.get('packages')
|
||||||
name = spec.name
|
names = set([spec.name])
|
||||||
|
names |= set(vspec.name for vspec in spec.package.virtuals_provided)
|
||||||
|
|
||||||
external_specs = []
|
external_specs = []
|
||||||
pkg_paths = allpkgs.get(name, {}).get('paths', None)
|
for name in names:
|
||||||
pkg_modules = allpkgs.get(name, {}).get('modules', None)
|
pkg_config = allpkgs.get(name, {})
|
||||||
if (not pkg_paths) and (not pkg_modules):
|
pkg_paths = pkg_config.get('paths', {})
|
||||||
return []
|
pkg_modules = pkg_config.get('modules', {})
|
||||||
|
if (not pkg_paths) and (not pkg_modules):
|
||||||
for external_spec, path in iteritems(pkg_paths):
|
|
||||||
if not path:
|
|
||||||
# skip entries without paths (avoid creating extra Specs)
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
external_spec = spack.spec.Spec(external_spec,
|
for external_spec, path in pkg_paths.items():
|
||||||
external_path=canonicalize_path(path))
|
external_spec = spack.spec.Spec(
|
||||||
if external_spec.satisfies(spec):
|
external_spec, external_path=canonicalize_path(path))
|
||||||
external_specs.append(external_spec)
|
if external_spec.satisfies(spec):
|
||||||
|
external_specs.append(external_spec)
|
||||||
|
|
||||||
for external_spec, module in iteritems(pkg_modules):
|
for external_spec, module in pkg_modules.items():
|
||||||
if not module:
|
external_spec = spack.spec.Spec(
|
||||||
continue
|
external_spec, external_module=module)
|
||||||
|
if external_spec.satisfies(spec):
|
||||||
external_spec = spack.spec.Spec(
|
external_specs.append(external_spec)
|
||||||
external_spec, external_module=module)
|
|
||||||
if external_spec.satisfies(spec):
|
|
||||||
external_specs.append(external_spec)
|
|
||||||
|
|
||||||
# defensively copy returned specs
|
# defensively copy returned specs
|
||||||
return [s.copy() for s in external_specs]
|
return [s.copy() for s in external_specs]
|
||||||
@ -215,12 +190,11 @@ def spec_externals(spec):
|
|||||||
|
|
||||||
def is_spec_buildable(spec):
|
def is_spec_buildable(spec):
|
||||||
"""Return true if the spec pkgspec is configured as buildable"""
|
"""Return true if the spec pkgspec is configured as buildable"""
|
||||||
allpkgs = get_packages_config()
|
allpkgs = spack.config.get('packages')
|
||||||
if spec.name not in allpkgs:
|
do_not_build = [name for name, entry in allpkgs.items()
|
||||||
return True
|
if not entry.get('buildable', True)]
|
||||||
if 'buildable' not in allpkgs[spec.name]:
|
return not (spec.name in do_not_build or
|
||||||
return True
|
any(spec.package.provides(name) for name in do_not_build))
|
||||||
return allpkgs[spec.name]['buildable']
|
|
||||||
|
|
||||||
|
|
||||||
def get_package_dir_permissions(spec):
|
def get_package_dir_permissions(spec):
|
||||||
|
@ -185,34 +185,6 @@ def test_develop(self):
|
|||||||
spec.concretize()
|
spec.concretize()
|
||||||
assert spec.version == Version('0.2.15.develop')
|
assert spec.version == Version('0.2.15.develop')
|
||||||
|
|
||||||
def test_no_virtuals_in_packages_yaml(self):
|
|
||||||
"""Verify that virtuals are not allowed in packages.yaml."""
|
|
||||||
|
|
||||||
# set up a packages.yaml file with a vdep as a key. We use
|
|
||||||
# syaml.load_config here to make sure source lines in the config are
|
|
||||||
# attached to parsed strings, as the error message uses them.
|
|
||||||
conf = syaml.load_config("""\
|
|
||||||
mpi:
|
|
||||||
paths:
|
|
||||||
mpi-with-lapack@2.1: /path/to/lapack
|
|
||||||
""")
|
|
||||||
spack.config.set('packages', conf, scope='concretize')
|
|
||||||
|
|
||||||
# now when we get the packages.yaml config, there should be an error
|
|
||||||
with pytest.raises(spack.package_prefs.VirtualInPackagesYAMLError):
|
|
||||||
spack.package_prefs.get_packages_config()
|
|
||||||
|
|
||||||
def test_all_is_not_a_virtual(self):
|
|
||||||
"""Verify that `all` is allowed in packages.yaml."""
|
|
||||||
conf = syaml.load_config("""\
|
|
||||||
all:
|
|
||||||
variants: [+mpi]
|
|
||||||
""")
|
|
||||||
spack.config.set('packages', conf, scope='concretize')
|
|
||||||
|
|
||||||
# should be no error for 'all':
|
|
||||||
spack.package_prefs.get_packages_config()
|
|
||||||
|
|
||||||
def test_external_mpi(self):
|
def test_external_mpi(self):
|
||||||
# make sure this doesn't give us an external first.
|
# make sure this doesn't give us an external first.
|
||||||
spec = Spec('mpi')
|
spec = Spec('mpi')
|
||||||
@ -236,6 +208,37 @@ def test_external_mpi(self):
|
|||||||
spec.concretize()
|
spec.concretize()
|
||||||
assert spec['mpich'].external_path == '/dummy/path'
|
assert spec['mpich'].external_path == '/dummy/path'
|
||||||
|
|
||||||
|
def test_external_module(self, monkeypatch):
|
||||||
|
"""Test that packages can find externals specified by module
|
||||||
|
|
||||||
|
The specific code for parsing the module is tested elsewhere.
|
||||||
|
This just tests that the preference is accounted for"""
|
||||||
|
# make sure this doesn't give us an external first.
|
||||||
|
def mock_module(cmd, module):
|
||||||
|
return 'prepend-path PATH /dummy/path'
|
||||||
|
monkeypatch.setattr(spack.util.module_cmd, 'module', mock_module)
|
||||||
|
|
||||||
|
spec = Spec('mpi')
|
||||||
|
spec.concretize()
|
||||||
|
assert not spec['mpi'].external
|
||||||
|
|
||||||
|
# load config
|
||||||
|
conf = syaml.load_config("""\
|
||||||
|
all:
|
||||||
|
providers:
|
||||||
|
mpi: [mpich]
|
||||||
|
mpi:
|
||||||
|
buildable: false
|
||||||
|
modules:
|
||||||
|
mpich@3.0.4: dummy
|
||||||
|
""")
|
||||||
|
spack.config.set('packages', conf, scope='concretize')
|
||||||
|
|
||||||
|
# ensure that once config is in place, external is used
|
||||||
|
spec = Spec('mpi')
|
||||||
|
spec.concretize()
|
||||||
|
assert spec['mpich'].external_path == '/dummy/path'
|
||||||
|
|
||||||
def test_config_permissions_from_all(self, configure_permissions):
|
def test_config_permissions_from_all(self, configure_permissions):
|
||||||
# Although these aren't strictly about concretization, they are
|
# Although these aren't strictly about concretization, they are
|
||||||
# configured in the same file and therefore convenient to test here.
|
# configured in the same file and therefore convenient to test here.
|
||||||
|
@ -1040,6 +1040,13 @@ def __init__(self, name, dependencies, dependency_types, conditions=None,
|
|||||||
self.conflicts = {}
|
self.conflicts = {}
|
||||||
self.patches = {}
|
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):
|
class MockPackageMultiRepo(object):
|
||||||
def __init__(self, packages):
|
def __init__(self, packages):
|
||||||
|
@ -52,52 +52,52 @@ def check_mirror():
|
|||||||
mirror_root = os.path.join(stage.path, 'test-mirror')
|
mirror_root = os.path.join(stage.path, 'test-mirror')
|
||||||
# register mirror with spack config
|
# register mirror with spack config
|
||||||
mirrors = {'spack-mirror-test': 'file://' + mirror_root}
|
mirrors = {'spack-mirror-test': 'file://' + mirror_root}
|
||||||
spack.config.set('mirrors', mirrors)
|
with spack.config.override('mirrors', mirrors):
|
||||||
with spack.config.override('config:checksum', False):
|
|
||||||
specs = [Spec(x).concretized() for x in repos]
|
|
||||||
spack.mirror.create(mirror_root, specs)
|
|
||||||
|
|
||||||
# Stage directory exists
|
|
||||||
assert os.path.isdir(mirror_root)
|
|
||||||
|
|
||||||
for spec in specs:
|
|
||||||
fetcher = spec.package.fetcher[0]
|
|
||||||
per_package_ref = os.path.join(
|
|
||||||
spec.name, '-'.join([spec.name, str(spec.version)]))
|
|
||||||
mirror_paths = spack.mirror.mirror_archive_paths(
|
|
||||||
fetcher,
|
|
||||||
per_package_ref)
|
|
||||||
expected_path = os.path.join(
|
|
||||||
mirror_root, mirror_paths.storage_path)
|
|
||||||
assert os.path.exists(expected_path)
|
|
||||||
|
|
||||||
# Now try to fetch each package.
|
|
||||||
for name, mock_repo in repos.items():
|
|
||||||
spec = Spec(name).concretized()
|
|
||||||
pkg = spec.package
|
|
||||||
|
|
||||||
with spack.config.override('config:checksum', False):
|
with spack.config.override('config:checksum', False):
|
||||||
with pkg.stage:
|
specs = [Spec(x).concretized() for x in repos]
|
||||||
pkg.do_stage(mirror_only=True)
|
spack.mirror.create(mirror_root, specs)
|
||||||
|
|
||||||
# Compare the original repo with the expanded archive
|
# Stage directory exists
|
||||||
original_path = mock_repo.path
|
assert os.path.isdir(mirror_root)
|
||||||
if 'svn' in name:
|
|
||||||
# have to check out the svn repo to compare.
|
|
||||||
original_path = os.path.join(
|
|
||||||
mock_repo.path, 'checked_out')
|
|
||||||
|
|
||||||
svn = which('svn', required=True)
|
for spec in specs:
|
||||||
svn('checkout', mock_repo.url, original_path)
|
fetcher = spec.package.fetcher[0]
|
||||||
|
per_package_ref = os.path.join(
|
||||||
|
spec.name, '-'.join([spec.name, str(spec.version)]))
|
||||||
|
mirror_paths = spack.mirror.mirror_archive_paths(
|
||||||
|
fetcher,
|
||||||
|
per_package_ref)
|
||||||
|
expected_path = os.path.join(
|
||||||
|
mirror_root, mirror_paths.storage_path)
|
||||||
|
assert os.path.exists(expected_path)
|
||||||
|
|
||||||
dcmp = filecmp.dircmp(
|
# Now try to fetch each package.
|
||||||
original_path, pkg.stage.source_path)
|
for name, mock_repo in repos.items():
|
||||||
|
spec = Spec(name).concretized()
|
||||||
|
pkg = spec.package
|
||||||
|
|
||||||
# make sure there are no new files in the expanded
|
with spack.config.override('config:checksum', False):
|
||||||
# tarball
|
with pkg.stage:
|
||||||
assert not dcmp.right_only
|
pkg.do_stage(mirror_only=True)
|
||||||
# and that all original files are present.
|
|
||||||
assert all(l in exclude for l in dcmp.left_only)
|
# Compare the original repo with the expanded archive
|
||||||
|
original_path = mock_repo.path
|
||||||
|
if 'svn' in name:
|
||||||
|
# have to check out the svn repo to compare.
|
||||||
|
original_path = os.path.join(
|
||||||
|
mock_repo.path, 'checked_out')
|
||||||
|
|
||||||
|
svn = which('svn', required=True)
|
||||||
|
svn('checkout', mock_repo.url, original_path)
|
||||||
|
|
||||||
|
dcmp = filecmp.dircmp(
|
||||||
|
original_path, pkg.stage.source_path)
|
||||||
|
|
||||||
|
# make sure there are no new files in the expanded
|
||||||
|
# tarball
|
||||||
|
assert not dcmp.right_only
|
||||||
|
# and that all original files are present.
|
||||||
|
assert all(l in exclude for l in dcmp.left_only)
|
||||||
|
|
||||||
|
|
||||||
def test_url_mirror(mock_archive):
|
def test_url_mirror(mock_archive):
|
||||||
|
@ -20,28 +20,11 @@
|
|||||||
'setenv LDFLAGS -L/path/to/lib',
|
'setenv LDFLAGS -L/path/to/lib',
|
||||||
'prepend-path PATH /path/to/bin']
|
'prepend-path PATH /path/to/bin']
|
||||||
|
|
||||||
|
_test_template = "'. %s 2>&1' % args[1]"
|
||||||
@pytest.fixture
|
|
||||||
def module_function_test_mode():
|
|
||||||
old_mode = spack.util.module_cmd._test_mode
|
|
||||||
spack.util.module_cmd._test_mode = True
|
|
||||||
|
|
||||||
yield
|
|
||||||
|
|
||||||
spack.util.module_cmd._test_mode = old_mode
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
def test_module_function_change_env(tmpdir, working_env, monkeypatch):
|
||||||
def save_module_func():
|
monkeypatch.setattr(spack.util.module_cmd, '_cmd_template', _test_template)
|
||||||
old_func = spack.util.module_cmd.module
|
|
||||||
|
|
||||||
yield
|
|
||||||
|
|
||||||
spack.util.module_cmd.module = old_func
|
|
||||||
|
|
||||||
|
|
||||||
def test_module_function_change_env(tmpdir, working_env,
|
|
||||||
module_function_test_mode):
|
|
||||||
src_file = str(tmpdir.join('src_me'))
|
src_file = str(tmpdir.join('src_me'))
|
||||||
with open(src_file, 'w') as f:
|
with open(src_file, 'w') as f:
|
||||||
f.write('export TEST_MODULE_ENV_VAR=TEST_SUCCESS\n')
|
f.write('export TEST_MODULE_ENV_VAR=TEST_SUCCESS\n')
|
||||||
@ -53,7 +36,8 @@ def test_module_function_change_env(tmpdir, working_env,
|
|||||||
assert os.environ['NOT_AFFECTED'] == "NOT_AFFECTED"
|
assert os.environ['NOT_AFFECTED'] == "NOT_AFFECTED"
|
||||||
|
|
||||||
|
|
||||||
def test_module_function_no_change(tmpdir, module_function_test_mode):
|
def test_module_function_no_change(tmpdir, monkeypatch):
|
||||||
|
monkeypatch.setattr(spack.util.module_cmd, '_cmd_template', _test_template)
|
||||||
src_file = str(tmpdir.join('src_me'))
|
src_file = str(tmpdir.join('src_me'))
|
||||||
with open(src_file, 'w') as f:
|
with open(src_file, 'w') as f:
|
||||||
f.write('echo TEST_MODULE_FUNCTION_PRINT')
|
f.write('echo TEST_MODULE_FUNCTION_PRINT')
|
||||||
@ -65,11 +49,11 @@ def test_module_function_no_change(tmpdir, module_function_test_mode):
|
|||||||
assert os.environ == old_env
|
assert os.environ == old_env
|
||||||
|
|
||||||
|
|
||||||
def test_get_path_from_module_faked(save_module_func):
|
def test_get_path_from_module_faked(monkeypatch):
|
||||||
for line in test_module_lines:
|
for line in test_module_lines:
|
||||||
def fake_module(*args):
|
def fake_module(*args):
|
||||||
return line
|
return line
|
||||||
spack.util.module_cmd.module = fake_module
|
monkeypatch.setattr(spack.util.module_cmd, 'module', fake_module)
|
||||||
|
|
||||||
path = get_path_from_module('mod')
|
path = get_path_from_module('mod')
|
||||||
assert path == '/path/to'
|
assert path == '/path/to'
|
||||||
|
@ -387,7 +387,6 @@ def test_unsatisfiable_architecture(self, set_dependency):
|
|||||||
with pytest.raises(spack.spec.UnsatisfiableArchitectureSpecError):
|
with pytest.raises(spack.spec.UnsatisfiableArchitectureSpecError):
|
||||||
spec.normalize()
|
spec.normalize()
|
||||||
|
|
||||||
@pytest.mark.usefixtures('config')
|
|
||||||
def test_invalid_dep(self):
|
def test_invalid_dep(self):
|
||||||
spec = Spec('libelf ^mpich')
|
spec = Spec('libelf ^mpich')
|
||||||
with pytest.raises(spack.spec.InvalidDependencyError):
|
with pytest.raises(spack.spec.InvalidDependencyError):
|
||||||
@ -602,7 +601,6 @@ def test_copy_normalized(self):
|
|||||||
copy_ids = set(id(s) for s in copy.traverse())
|
copy_ids = set(id(s) for s in copy.traverse())
|
||||||
assert not orig_ids.intersection(copy_ids)
|
assert not orig_ids.intersection(copy_ids)
|
||||||
|
|
||||||
@pytest.mark.usefixtures('config')
|
|
||||||
def test_copy_concretized(self):
|
def test_copy_concretized(self):
|
||||||
orig = Spec('mpileaks')
|
orig = Spec('mpileaks')
|
||||||
orig.concretize()
|
orig.concretize()
|
||||||
|
@ -19,16 +19,11 @@
|
|||||||
# If we need another option that changes the environment, add it here.
|
# If we need another option that changes the environment, add it here.
|
||||||
module_change_commands = ['load', 'swap', 'unload', 'purge', 'use', 'unuse']
|
module_change_commands = ['load', 'swap', 'unload', 'purge', 'use', 'unuse']
|
||||||
py_cmd = "'import os;import json;print(json.dumps(dict(os.environ)))'"
|
py_cmd = "'import os;import json;print(json.dumps(dict(os.environ)))'"
|
||||||
|
_cmd_template = "'module ' + ' '.join(args) + ' 2>&1'"
|
||||||
# This is just to enable testing. I hate it but we can't find a better way
|
|
||||||
_test_mode = False
|
|
||||||
|
|
||||||
|
|
||||||
def module(*args):
|
def module(*args):
|
||||||
module_cmd = 'module ' + ' '.join(args) + ' 2>&1'
|
module_cmd = eval(_cmd_template) # So we can monkeypatch for testing
|
||||||
if _test_mode:
|
|
||||||
tty.warn('module function operating in test mode')
|
|
||||||
module_cmd = ". %s 2>&1" % args[1]
|
|
||||||
if args[0] in module_change_commands:
|
if args[0] in module_change_commands:
|
||||||
# Do the module manipulation, then output the environment in JSON
|
# Do the module manipulation, then output the environment in JSON
|
||||||
# and read the JSON back in the parent process to update os.environ
|
# and read the JSON back in the parent process to update os.environ
|
||||||
|
Loading…
Reference in New Issue
Block a user