diff --git a/easybuild/tools/modules.py b/easybuild/tools/modules.py index 14509e79d8..3e3f004dc5 100644 --- a/easybuild/tools/modules.py +++ b/easybuild/tools/modules.py @@ -1443,6 +1443,21 @@ def use(self, path, priority=None): ('' if cur_mod_path is None else cur_mod_path, new_mod_path)) os.environ['MODULEPATH'] = new_mod_path + def unuse(self, path): + """Remove a module path""" + # We can simply remove the path from MODULEPATH to avoid the costly module call + cur_mod_path = os.environ.get('MODULEPATH') + if cur_mod_path is not None: + # Removing the last entry unsets the variable + if cur_mod_path == path: + self.log.debug('Changing MODULEPATH from %s to ' % cur_mod_path) + del os.environ['MODULEPATH'] + else: + new_mod_path = ':'.join(p for p in cur_mod_path.split(':') if p != path) + if new_mod_path != cur_mod_path: + self.log.debug('Changing MODULEPATH from %s to %s' % (cur_mod_path, new_mod_path)) + os.environ['MODULEPATH'] = new_mod_path + def prepend_module_path(self, path, set_mod_paths=True, priority=None): """ Prepend given module path to list of module paths, or bump it to 1st place. diff --git a/test/framework/modules.py b/test/framework/modules.py index c71b5f4360..a2f4633787 100644 --- a/test/framework/modules.py +++ b/test/framework/modules.py @@ -1157,11 +1157,11 @@ def test_module_use_unuse(self): self.assertFalse(test_dir1 in os.environ.get('MODULEPATH', '')) self.modtool.use(test_dir1) - self.assertTrue(os.environ.get('MODULEPATH', '').startswith('%s:' % test_dir1)) + self.assertTrue(os.environ['MODULEPATH'].startswith('%s:' % test_dir1)) self.modtool.use(test_dir2) - self.assertTrue(os.environ.get('MODULEPATH', '').startswith('%s:' % test_dir2)) + self.assertTrue(os.environ['MODULEPATH'].startswith('%s:' % test_dir2)) self.modtool.use(test_dir3) - self.assertTrue(os.environ.get('MODULEPATH', '').startswith('%s:' % test_dir3)) + self.assertTrue(os.environ['MODULEPATH'].startswith('%s:' % test_dir3)) # make sure the right test module is loaded self.modtool.load(['test']) @@ -1193,8 +1193,9 @@ def test_module_use_unuse(self): self.assertEqual(os.getenv('TEST123'), 'two') self.modtool.unload(['test']) - # check whether prepend with priority actually works (only for Lmod) + # Tests for Lmod only if isinstance(self.modtool, Lmod): + # check whether prepend with priority actually works (priority is specific to Lmod) self.modtool.use(test_dir1, priority=100) self.modtool.use(test_dir3) self.assertTrue(os.environ['MODULEPATH'].startswith('%s:%s:%s:' % (test_dir2, test_dir1, test_dir3))) @@ -1212,6 +1213,28 @@ def test_module_use_unuse(self): self.assertEqual(os.getenv('TEST123'), 'three') self.modtool.unload(['test']) + # Check load and unload for a single path when it is the only one + # Only for Lmod as we have some shortcuts for avoiding the module call there + old_module_path = os.environ['MODULEPATH'] + del os.environ['MODULEPATH'] + self.modtool.use(test_dir1) + self.assertEqual(os.environ['MODULEPATH'], test_dir1) + self.modtool.unuse(test_dir1) + self.assertFalse('MODULEPATH' in os.environ) + os.environ['MODULEPATH'] = old_module_path # Restore + + # Using an empty path still works (technically) (Lmod only, ignored by Tcl) + old_module_path = os.environ['MODULEPATH'] + self.modtool.use('') + self.assertEqual(os.environ['MODULEPATH'], ':' + old_module_path) + self.modtool.unuse('') + self.assertEqual(os.environ['MODULEPATH'], old_module_path) + # Even works when the whole path is empty + os.environ['MODULEPATH'] = '' + self.modtool.unuse('') + self.assertFalse('MODULEPATH' in os.environ) + os.environ['MODULEPATH'] = old_module_path # Restore + def test_module_use_bash(self): """Test whether effect of 'module use' is preserved when a new bash session is started.""" # this test is here as check for a nasty bug in how the modules tool is deployed