Skip to content

Commit 74a4c03

Browse files
authored
Merge pull request #3085 from wpoely86/modprovides
adds support for including 'extensions' statement in Lua modules with Lmod 8.2+
2 parents e196437 + 07e58f6 commit 74a4c03

File tree

2 files changed

+62
-1
lines changed

2 files changed

+62
-1
lines changed

easybuild/tools/module_generator.py

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,14 @@ def comment(self, msg):
364364
"""Return given string formatted as a comment."""
365365
raise NotImplementedError
366366

367+
def check_version(self, minimal_version_maj, minimal_version_min):
368+
"""
369+
Check the minimal version of the modules tool in the module file
370+
:param minimal_version_maj: the major version to check
371+
:param minimal_version_min: the minor version to check
372+
"""
373+
raise NotImplementedError
374+
367375
def conditional_statement(self, conditions, body, negative=False, else_body=None, indent=True,
368376
cond_or=False, cond_tmpl=None):
369377
"""
@@ -520,6 +528,16 @@ def _generate_extension_list(self):
520528

521529
return extensions
522530

531+
def _generate_extensions_list(self):
532+
"""
533+
Generate a list of all extensions in name/version format
534+
"""
535+
exts_list = self.app.cfg['exts_list']
536+
# the format is extension_name/extension_version
537+
exts_ver_list = sorted(['%s/%s' % (ext[0], ext[1]) for ext in exts_list], key=str.lower)
538+
539+
return exts_ver_list
540+
523541
def _generate_help_text(self):
524542
"""
525543
Generate syntax-independent help text used for `module help`.
@@ -738,7 +756,7 @@ def get_description(self, conflict=True):
738756
# - 'conflict Compiler/GCC/4.8.2/OpenMPI' for 'Compiler/GCC/4.8.2/OpenMPI/1.6.4'
739757
lines.extend(['', "conflict %s" % os.path.dirname(self.app.short_mod_name)])
740758

741-
whatis_lines = ["module-whatis {%s}" % re.sub('([{}\[\]])', r'\\\1', l) for l in self._generate_whatis_lines()]
759+
whatis_lines = ["module-whatis {%s}" % re.sub(r'([{}\[\]])', r'\\\1', l) for l in self._generate_whatis_lines()]
742760
txt += '\n'.join([''] + lines + ['']) % {
743761
'name': self.app.name,
744762
'version': self.app.version,
@@ -1017,6 +1035,18 @@ def __init__(self, *args, **kwargs):
10171035
if self.modules_tool.version and LooseVersion(self.modules_tool.version) >= LooseVersion('7.7.38'):
10181036
self.DOT_MODULERC = '.modulerc.lua'
10191037

1038+
def check_version(self, minimal_version_maj, minimal_version_min):
1039+
"""
1040+
Check the minimal version of the moduletool in the module file
1041+
:param minimal_version_maj: the major version to check
1042+
:param minimal_version_min: the minor version to check
1043+
"""
1044+
lmod_version_check_expr = 'convertToCanonical(LmodVersion()) > convertToCanonical("%(ver_maj)s.%(ver_min)s")'
1045+
return lmod_version_check_expr % {
1046+
'ver_maj': minimal_version_maj,
1047+
'ver_min': minimal_version_min,
1048+
}
1049+
10201050
def check_group(self, group, error_msg=None):
10211051
"""
10221052
Generate a check of the software group and the current user, and refuse to load the module if the user don't
@@ -1129,6 +1159,14 @@ def get_description(self, conflict=True):
11291159
for line in self._generate_whatis_lines():
11301160
whatis_lines.append("whatis(%s%s%s)" % (self.START_STR, self.check_str(line), self.END_STR))
11311161

1162+
extensions_list = self._generate_extensions_list()
1163+
1164+
if extensions_list:
1165+
extensions_stmt = 'extensions(%s)' % ', '.join(['"%s"' % x for x in extensions_list])
1166+
# put this behind a Lmod version check as 'extensions' is only supported since Lmod 8.2.0,
1167+
# see https://lmod.readthedocs.io/en/latest/330_extensions.html#module-extensions
1168+
lines.extend(['', self.conditional_statement(self.check_version("8", "2"), extensions_stmt)])
1169+
11321170
txt += '\n'.join([''] + lines + ['']) % {
11331171
'name': self.app.name,
11341172
'version': self.app.version,

test/framework/module_generator.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
"""
3131
import glob
3232
import os
33+
import re
3334
import sys
3435
import tempfile
3536
from distutils.version import LooseVersion
@@ -694,6 +695,28 @@ def test_append_paths(self):
694695
"which only expects relative paths." % self.modgen.app.installdir,
695696
self.modgen.append_paths, "key2", ["bar", "%s/foo" % self.modgen.app.installdir])
696697

698+
def test_module_extensions(self):
699+
"""test the extensions() for extensions"""
700+
# not supported for Tcl modules
701+
if self.MODULE_GENERATOR_CLASS == ModuleGeneratorTcl:
702+
return
703+
704+
test_dir = os.path.abspath(os.path.dirname(__file__))
705+
os.environ['MODULEPATH'] = os.path.join(test_dir, 'modules')
706+
test_ec = os.path.join(test_dir, 'easyconfigs', 'test_ecs', 't', 'toy', 'toy-0.0-gompi-2018a-test.eb')
707+
708+
ec = EasyConfig(test_ec)
709+
eb = EasyBlock(ec)
710+
modgen = self.MODULE_GENERATOR_CLASS(eb)
711+
desc = modgen.get_description()
712+
713+
patterns = []
714+
if self.MODULE_GENERATOR_CLASS == ModuleGeneratorLua:
715+
patterns.append(r'^\s*extensions\("bar/0.0", "barbar/0.0", "l/s", "toy/0.0"\)')
716+
717+
for pattern in patterns:
718+
self.assertTrue(re.search(pattern, desc, re.M), "Pattern '%s' found in: %s" % (pattern, desc))
719+
697720
def test_prepend_paths(self):
698721
"""Test generating prepend-paths statements."""
699722
# test prepend_paths

0 commit comments

Comments
 (0)