summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTodd Gamblin <tgamblin@llnl.gov>2016-06-26 23:33:48 -0700
committerGitHub <noreply@github.com>2016-06-26 23:33:48 -0700
commit73213ac59d36d474267a482e9300c048ed02a757 (patch)
treeeaed0ca5348d2b40bb267a0699e0da0d38f59090
parenta1db306a0c389e297928802c257c2c5444588724 (diff)
parent670669ef808a9a737e760ced8a9fd1d000f360b9 (diff)
downloadspack-73213ac59d36d474267a482e9300c048ed02a757.tar.gz
spack-73213ac59d36d474267a482e9300c048ed02a757.tar.bz2
spack-73213ac59d36d474267a482e9300c048ed02a757.tar.xz
spack-73213ac59d36d474267a482e9300c048ed02a757.zip
Merge pull request #984 from epfl-scitas/module_file_explicit_load
module files : explicit load and mnemonic suffixes
-rw-r--r--lib/spack/spack/config.py2
-rw-r--r--lib/spack/spack/modules.py21
-rw-r--r--lib/spack/spack/test/modules.py172
3 files changed, 185 insertions, 10 deletions
diff --git a/lib/spack/spack/config.py b/lib/spack/spack/config.py
index db0787edc6..84179e1469 100644
--- a/lib/spack/spack/config.py
+++ b/lib/spack/spack/config.py
@@ -307,6 +307,8 @@ section_schemas = {
'autoload': {'$ref': '#/definitions/dependency_selection'},
'prerequisites': {'$ref': '#/definitions/dependency_selection'},
'conflict': {'$ref': '#/definitions/array_of_strings'},
+ 'load': {'$ref': '#/definitions/array_of_strings'},
+ 'suffixes': {'$ref': '#/definitions/dictionary_of_strings'},
'environment': {
'type': 'object',
'default': {},
diff --git a/lib/spack/spack/modules.py b/lib/spack/spack/modules.py
index d2b819e80a..fb58be6ce0 100644
--- a/lib/spack/spack/modules.py
+++ b/lib/spack/spack/modules.py
@@ -285,11 +285,18 @@ class EnvModule(object):
naming_tokens = self.tokens
naming_scheme = self.naming_scheme
name = naming_scheme.format(**naming_tokens)
- name += '-' + self.spec.dag_hash(
- ) # Always append the hash to make the module file unique
# Not everybody is working on linux...
parts = name.split('/')
name = join_path(*parts)
+ # Add optional suffixes based on constraints
+ configuration, _ = parse_config_options(self)
+ suffixes = [name]
+ for constraint, suffix in configuration.get('suffixes', {}).items():
+ if constraint in self.spec:
+ suffixes.append(suffix)
+ # Always append the hash to make the module file unique
+ suffixes.append(self.spec.dag_hash())
+ name = '-'.join(suffixes)
return name
@property
@@ -381,6 +388,8 @@ class EnvModule(object):
for x in filter_blacklisted(
module_configuration.pop('autoload', []), self.name):
module_file_content += self.autoload(x)
+ for x in module_configuration.pop('load', []):
+ module_file_content += self.autoload(x)
for x in filter_blacklisted(
module_configuration.pop('prerequisites', []), self.name):
module_file_content += self.prerequisite(x)
@@ -402,8 +411,12 @@ class EnvModule(object):
return tuple()
def autoload(self, spec):
- m = type(self)(spec)
- return self.autoload_format.format(module_file=m.use_name)
+ if not isinstance(spec, str):
+ m = type(self)(spec)
+ module_file = m.use_name
+ else:
+ module_file = spec
+ return self.autoload_format.format(module_file=module_file)
def prerequisite(self, spec):
m = type(self)(spec)
diff --git a/lib/spack/spack/test/modules.py b/lib/spack/spack/test/modules.py
index 582e067860..443e4d13a6 100644
--- a/lib/spack/spack/test/modules.py
+++ b/lib/spack/spack/test/modules.py
@@ -27,6 +27,7 @@ from contextlib import contextmanager
import StringIO
import spack.modules
+import unittest
from spack.test.mock_packages_test import MockPackagesTest
FILE_REGISTRY = collections.defaultdict(StringIO.StringIO)
@@ -67,6 +68,24 @@ configuration_autoload_all = {
}
}
+configuration_prerequisites_direct = {
+ 'enable': ['tcl'],
+ 'tcl': {
+ 'all': {
+ 'prerequisites': 'direct'
+ }
+ }
+}
+
+configuration_prerequisites_all = {
+ 'enable': ['tcl'],
+ 'tcl': {
+ 'all': {
+ 'prerequisites': 'all'
+ }
+ }
+}
+
configuration_alter_environment = {
'enable': ['tcl'],
'tcl': {
@@ -74,8 +93,13 @@ configuration_alter_environment = {
'filter': {'environment_blacklist': ['CMAKE_PREFIX_PATH']}
},
'platform=test target=x86_64': {
- 'environment': {'set': {'FOO': 'foo'},
- 'unset': ['BAR']}
+ 'environment': {
+ 'set': {'FOO': 'foo'},
+ 'unset': ['BAR']
+ }
+ },
+ 'platform=test target=x86_32': {
+ 'load': ['foo/bar']
}
}
}
@@ -83,7 +107,8 @@ configuration_alter_environment = {
configuration_blacklist = {
'enable': ['tcl'],
'tcl': {
- 'blacklist': ['callpath'],
+ 'whitelist': ['zmpi'],
+ 'blacklist': ['callpath', 'mpi'],
'all': {
'autoload': 'direct'
}
@@ -100,8 +125,68 @@ configuration_conflicts = {
}
}
+configuration_wrong_conflicts = {
+ 'enable': ['tcl'],
+ 'tcl': {
+ 'naming_scheme': '{name}/{version}-{compiler.name}',
+ 'all': {
+ 'conflict': ['{name}/{compiler.name}']
+ }
+ }
+}
+
+configuration_suffix = {
+ 'enable': ['tcl'],
+ 'tcl': {
+ 'mpileaks': {
+ 'suffixes': {
+ '+debug': 'foo',
+ '~debug': 'bar'
+ }
+ }
+ }
+}
+
+
+class HelperFunctionsTests(unittest.TestCase):
+
+ def test_update_dictionary_extending_list(self):
+ target = {
+ 'foo': {
+ 'a': 1,
+ 'b': 2,
+ 'd': 4
+ },
+ 'bar': [1, 2, 4],
+ 'baz': 'foobar'
+ }
+ update = {
+ 'foo': {
+ 'c': 3,
+ },
+ 'bar': [3],
+ 'baz': 'foobaz',
+ 'newkey': {
+ 'd': 4
+ }
+ }
+ spack.modules.update_dictionary_extending_lists(target, update)
+ self.assertTrue(len(target) == 4)
+ self.assertTrue(len(target['foo']) == 4)
+ self.assertTrue(len(target['bar']) == 4)
+ self.assertEqual(target['baz'], 'foobaz')
+
+ def test_inspect_path(self):
+ env = spack.modules.inspect_path('/usr')
+ names = [item.name for item in env]
+ self.assertTrue('PATH' in names)
+ self.assertTrue('LIBRARY_PATH' in names)
+ self.assertTrue('LD_LIBRARY_PATH' in names)
+ self.assertTrue('CPATH' in names)
+
class TclTests(MockPackagesTest):
+
def setUp(self):
super(TclTests, self).setUp()
self.configuration_obj = spack.modules.CONFIGURATION
@@ -116,7 +201,6 @@ class TclTests(MockPackagesTest):
def get_modulefile_content(self, spec):
spec.concretize()
- print spec, '&&&&&'
generator = spack.modules.TclModule(spec)
generator.write()
content = FILE_REGISTRY[generator.file_name].split('\n')
@@ -127,6 +211,8 @@ class TclTests(MockPackagesTest):
spec = spack.spec.Spec('mpich@3.0.4')
content = self.get_modulefile_content(spec)
self.assertTrue('module-whatis "mpich @3.0.4"' in content)
+ self.assertRaises(TypeError, spack.modules.dependencies,
+ spec, 'non-existing-tag')
def test_autoload(self):
spack.modules.CONFIGURATION = configuration_autoload_direct
@@ -141,11 +227,21 @@ class TclTests(MockPackagesTest):
self.assertEqual(len([x for x in content if 'is-loaded' in x]), 5)
self.assertEqual(len([x for x in content if 'module load ' in x]), 5)
+ def test_prerequisites(self):
+ spack.modules.CONFIGURATION = configuration_prerequisites_direct
+ spec = spack.spec.Spec('mpileaks arch=x86-linux')
+ content = self.get_modulefile_content(spec)
+ self.assertEqual(len([x for x in content if 'prereq' in x]), 2)
+
+ spack.modules.CONFIGURATION = configuration_prerequisites_all
+ spec = spack.spec.Spec('mpileaks arch=x86-linux')
+ content = self.get_modulefile_content(spec)
+ self.assertEqual(len([x for x in content if 'prereq' in x]), 5)
+
def test_alter_environment(self):
spack.modules.CONFIGURATION = configuration_alter_environment
spec = spack.spec.Spec('mpileaks platform=test target=x86_64')
content = self.get_modulefile_content(spec)
- print content
self.assertEqual(
len([x
for x in content
@@ -156,7 +252,6 @@ class TclTests(MockPackagesTest):
spec = spack.spec.Spec('libdwarf %clang platform=test target=x86_32')
content = self.get_modulefile_content(spec)
- print content
self.assertEqual(
len([x
for x in content
@@ -164,6 +259,10 @@ class TclTests(MockPackagesTest):
self.assertEqual(
len([x for x in content if 'setenv FOO "foo"' in x]), 0)
self.assertEqual(len([x for x in content if 'unsetenv BAR' in x]), 0)
+ self.assertEqual(
+ len([x for x in content if 'is-loaded foo/bar' in x]), 1)
+ self.assertEqual(
+ len([x for x in content if 'module load foo/bar' in x]), 1)
def test_blacklist(self):
spack.modules.CONFIGURATION = configuration_blacklist
@@ -171,6 +270,13 @@ class TclTests(MockPackagesTest):
content = self.get_modulefile_content(spec)
self.assertEqual(len([x for x in content if 'is-loaded' in x]), 1)
self.assertEqual(len([x for x in content if 'module load ' in x]), 1)
+ spec = spack.spec.Spec('callpath arch=x86-linux')
+ # Returns a StringIO instead of a string as no module file was written
+ self.assertRaises(AttributeError, self.get_modulefile_content, spec)
+ spec = spack.spec.Spec('zmpi arch=x86-linux')
+ content = self.get_modulefile_content(spec)
+ self.assertEqual(len([x for x in content if 'is-loaded' in x]), 1)
+ self.assertEqual(len([x for x in content if 'module load ' in x]), 1)
def test_conflicts(self):
spack.modules.CONFIGURATION = configuration_conflicts
@@ -182,3 +288,57 @@ class TclTests(MockPackagesTest):
len([x for x in content if x == 'conflict mpileaks']), 1)
self.assertEqual(
len([x for x in content if x == 'conflict intel/14.0.1']), 1)
+
+ spack.modules.CONFIGURATION = configuration_wrong_conflicts
+ self.assertRaises(SystemExit, self.get_modulefile_content, spec)
+
+ def test_suffixes(self):
+ spack.modules.CONFIGURATION = configuration_suffix
+ spec = spack.spec.Spec('mpileaks+debug arch=x86-linux')
+ spec.concretize()
+ generator = spack.modules.TclModule(spec)
+ self.assertTrue('foo' in generator.use_name)
+
+ spec = spack.spec.Spec('mpileaks~debug arch=x86-linux')
+ spec.concretize()
+ generator = spack.modules.TclModule(spec)
+ self.assertTrue('bar' in generator.use_name)
+
+
+configuration_dotkit = {
+ 'enable': ['dotkit'],
+ 'dotkit': {
+ 'all': {
+ 'prerequisites': 'direct'
+ }
+ }
+}
+
+
+class DotkitTests(MockPackagesTest):
+
+ def setUp(self):
+ super(DotkitTests, self).setUp()
+ self.configuration_obj = spack.modules.CONFIGURATION
+ spack.modules.open = mock_open
+ # Make sure that a non-mocked configuration will trigger an error
+ spack.modules.CONFIGURATION = None
+
+ def tearDown(self):
+ del spack.modules.open
+ spack.modules.CONFIGURATION = self.configuration_obj
+ super(DotkitTests, self).tearDown()
+
+ def get_modulefile_content(self, spec):
+ spec.concretize()
+ generator = spack.modules.Dotkit(spec)
+ generator.write()
+ content = FILE_REGISTRY[generator.file_name].split('\n')
+ return content
+
+ def test_dotkit(self):
+ spack.modules.CONFIGURATION = configuration_dotkit
+ spec = spack.spec.Spec('mpileaks arch=x86-linux')
+ content = self.get_modulefile_content(spec)
+ self.assertTrue('#c spack' in content)
+ self.assertTrue('#d mpileaks @2.3' in content)