Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adapt module function check for Environment Modules v4+ #4371

Merged
merged 1 commit into from
Dec 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions easybuild/tools/modules.py
Original file line number Diff line number Diff line change
Expand Up @@ -1328,6 +1328,31 @@ class EnvironmentModules(EnvironmentModulesTcl):
MAX_VERSION = None
VERSION_REGEXP = r'^Modules\s+Release\s+(?P<version>\d\S*)\s'

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
# Modules 4.2.0..5.0.1: module command is called from _module_raw shell function if it has
# been initialized in an interactive shell session (i.e., a session attached to a tty)
if self.testing:
if '_module_raw' in os.environ:
out, ec = os.environ['_module_raw'], 0
else:
out, ec = None, 1
else:
cmd = "type _module_raw"
out, ec = run_cmd(cmd, simple=False, log_ok=False, log_all=False, force_in_dry_run=True, trace=False)

if regex is None:
regex = r".*%s" % os.path.basename(self.cmd)
mod_cmd_re = re.compile(regex, re.M)

if ec == 0 and mod_cmd_re.search(out):
self.log.debug("Found pattern '%s' in defined '_module_raw' function." % mod_cmd_re.pattern)
else:
xdelaruelle marked this conversation as resolved.
Show resolved Hide resolved
self.log.debug("Pattern '%s' not found in '_module_raw' function, falling back to 'module' function",
mod_cmd_re.pattern)
super(EnvironmentModules, self).check_module_function(allow_mismatch, regex)

def check_module_output(self, cmd, stdout, stderr):
"""Check output of 'module' command, see if if is potentially invalid."""
if "_mlstatus = False" in stdout:
Expand Down
1 change: 1 addition & 0 deletions easybuild/tools/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
"sysctl -n machdep.cpu.brand_string", # used in get_cpu_model (OS X)
"sysctl -n machdep.cpu.vendor", # used in get_cpu_vendor (OS X)
"type module", # used in ModulesTool.check_module_function
"type _module_raw", # used in EnvironmentModules.check_module_function
"ulimit -u", # used in det_parallelism
]

Expand Down
19 changes: 18 additions & 1 deletion test/framework/modulestool.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
from easybuild.tools import modules, StrictVersion
from easybuild.tools.build_log import EasyBuildError
from easybuild.tools.filetools import read_file, which, write_file
from easybuild.tools.modules import Lmod
from easybuild.tools.modules import EnvironmentModules, Lmod
from test.framework.utilities import init_config


Expand Down Expand Up @@ -192,6 +192,23 @@ def test_lmod_specific(self):
# test updating local spider cache (but don't actually update the local cache file!)
self.assertTrue(lmod.update(), "Updated local Lmod spider cache is non-empty")

def test_environment_modules_specific(self):
"""Environment Modules-specific test (skipped unless installed)."""
modulecmd_abspath = which(EnvironmentModules.COMMAND)
# only run this test if 'modulecmd.tcl' is installed
if modulecmd_abspath is not None:
# redefine 'module' and '_module_raw' function (deliberate mismatch with used module
# command in EnvironmentModules)
os.environ['_module_raw'] = "() { eval `/usr/share/Modules/libexec/foo.tcl' bash $*`;\n}"
os.environ['module'] = "() { _module_raw \"$@\" 2>&1;\n}"
error_regex = ".*pattern .* not found in defined 'module' function"
self.assertErrorRegex(EasyBuildError, error_regex, EnvironmentModules, testing=True)

# redefine '_module_raw' function with correct module command
os.environ['_module_raw'] = "() { eval `/usr/share/Modules/libexec/modulecmd.tcl' bash $*`;\n}"
mt = EnvironmentModules(testing=True)
self.assertIsInstance(mt.loaded_modules(), list) # dummy usage

def tearDown(self):
"""Testcase cleanup."""
super(ModulesToolTest, self).tearDown()
Expand Down
Loading