diff --git a/easybuild/tools/modules.py b/easybuild/tools/modules.py index a2295934c2..7d7181fe30 100644 --- a/easybuild/tools/modules.py +++ b/easybuild/tools/modules.py @@ -1328,6 +1328,29 @@ class EnvironmentModules(EnvironmentModulesTcl): MAX_VERSION = None VERSION_REGEXP = r'^Modules\s+Release\s+(?P\d\S*)\s' + def __init__(self, *args, **kwargs): + """Constructor, set Environment Modules-specific class variable values.""" + # ensure in-depth modulepath search (MODULES_AVAIL_INDEPTH has been introduced in v4.3) + setvar('MODULES_AVAIL_INDEPTH', '1', verbose=False) + # match against module name start (MODULES_SEARCH_MATCH has been introduced in v4.3) + setvar('MODULES_SEARCH_MATCH', 'starts_with', verbose=False) + # ensure no debug message (MODULES_VERBOSITY has been introduced in v4.3) + setvar('MODULES_VERBOSITY', 'normal', verbose=False) + # make module search case sensitive (search is case insensitive by default since v5.0) + setvar('MODULES_ICASE', 'never', verbose=False) + # disable extended default (introduced in v4.4 and enabled by default in v5.0) + setvar('MODULES_EXTENDED_DEFAULT', '0', verbose=False) + # hard disable output redirection, output messages are expected on stderr + setvar('MODULES_REDIRECT_OUTPUT', '0', verbose=False) + # make sure modulefile cache is ignored (cache mechanism supported since v5.3) + setvar('MODULES_IGNORE_CACHE', '1', verbose=False) + # ensure only module names are returned on avail (MODULES_AVAIL_TERSE_OUTPUT added in v4.7) + setvar('MODULES_AVAIL_TERSE_OUTPUT', '', verbose=False) + # ensure only module names are returned on list (MODULES_LIST_TERSE_OUTPUT added in v4.7) + setvar('MODULES_LIST_TERSE_OUTPUT', '', verbose=False) + + super(EnvironmentModules, self).__init__(*args, **kwargs) + def check_module_function(self, allow_mismatch=False, regex=None): """Check whether selected module tool matches 'module' function definition.""" # Modules 5.1.0+: module command is called from _module_raw shell function @@ -1360,6 +1383,27 @@ def check_module_output(self, cmd, stdout, stderr): else: self.log.debug("No errors detected when running module command '%s'", cmd) + def get_setenv_value_from_modulefile(self, mod_name, var_name): + """ + Get value for specific 'setenv' statement from module file for the specified module. + + :param mod_name: module name + :param var_name: name of the variable being set for which value should be returned + """ + # Tcl-based module tools produce "module show" output with setenv statements like: + # "setenv GCC_PATH /opt/gcc/8.3.0" + # "setenv VAR {some text} + # - line starts with 'setenv' + # - whitespace (spaces & tabs) around variable name + # - curly braces around value if it contain spaces + value = super(EnvironmentModules, self).get_setenv_value_from_modulefile(mod_name=mod_name, + var_name=var_name) + + if value: + value = value.strip('{}') + + return value + class Lmod(ModulesTool): """Interface to Lmod.""" diff --git a/test/framework/modules.py b/test/framework/modules.py index 4a8a6b15df..c2460c7a11 100644 --- a/test/framework/modules.py +++ b/test/framework/modules.py @@ -437,9 +437,8 @@ def test_load(self): # if GCC is loaded again, $EBROOTGCC should be set again, and GCC should be listed last self.modtool.load(['GCC/6.4.0-2.28']) - # environment modules v4.0 does not reload already loaded modules, will be changed in v4.2 - modtool_ver = StrictVersion(self.modtool.version) - if not isinstance(self.modtool, EnvironmentModules) or modtool_ver >= StrictVersion('4.2'): + # environment modules v4+ does not reload already loaded modules + if not isinstance(self.modtool, EnvironmentModules): self.assertTrue(os.environ.get('EBROOTGCC')) if isinstance(self.modtool, Lmod):