From f4dda1ea638f11f16652ab00ca88b72b96ea7762 Mon Sep 17 00:00:00 2001 From: Xavier Delaruelle Date: Sun, 29 Oct 2023 11:16:30 +0100 Subject: [PATCH 1/3] Fix test_load test for EnvironmentModules 4.2+ test_load expects that version 4.2+ of Environment Modules reload an already loaded module. As of version 5.3, already loaded modules are not reloaded unless one of their dependent module is unloaded or loaded. --- test/framework/modules.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/framework/modules.py b/test/framework/modules.py index 7bf87130bd..738cc79595 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): From 94ff50f8df8c0dfa05c6bec94bf32900112b8100 Mon Sep 17 00:00:00 2001 From: Xavier Delaruelle Date: Sun, 29 Oct 2023 11:26:15 +0100 Subject: [PATCH 2/3] Ensure correct configuration for EnvironmentModules Defines environment variables when initializing EnvironmentModules object to ensure that this module tool will not be influenced by external configuration. Setup Environment Modules configuration to ensure module search behaves like EasyBuild expects (match module name start, case sensitive, return in-depth modulepath content, ignore cache file). Also defines a basic output configuration not to get unexpected content like tags or variants. This change helps to pass "test_avail" test with Environment Modules v5.0+. --- easybuild/tools/modules.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/easybuild/tools/modules.py b/easybuild/tools/modules.py index 386643e706..aa739f7563 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_output(self, cmd, stdout, stderr): """Check output of 'module' command, see if if is potentially invalid.""" if "_mlstatus = False" in stdout: From f297d321b276730a6a5b806e60e266342012b999 Mon Sep 17 00:00:00 2001 From: Xavier Delaruelle Date: Sun, 29 Oct 2023 11:35:32 +0100 Subject: [PATCH 3/3] Setenv value may be enclosed in curly braces on EnvironmentModules Starting Environment Modules 4.2, value of setenv statement in "module show" output is enclosed in curly braces if it contains spaces. This change helps to pass "test_get_setenv_value_from_modulefile" test with Environment Modules v4.2+ --- easybuild/tools/modules.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/easybuild/tools/modules.py b/easybuild/tools/modules.py index aa739f7563..e0eda91aeb 100644 --- a/easybuild/tools/modules.py +++ b/easybuild/tools/modules.py @@ -1358,6 +1358,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."""