From c9c84b6c4ab9767e908aaddc436c44442a05ad79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20Jos=C3=A9=20Gonz=C3=A1lez=20Carrillo?= Date: Thu, 9 Mar 2023 18:32:37 +0100 Subject: [PATCH 1/2] Added modunloadmsg module option --- easybuild/framework/easyblock.py | 7 ++++++ easybuild/framework/easyconfig/default.py | 1 + easybuild/tools/module_generator.py | 23 +++++++++++++++++ test/framework/easyconfig.py | 10 ++++++++ test/framework/module_generator.py | 30 +++++++++++++++++++++++ 5 files changed, 71 insertions(+) diff --git a/easybuild/framework/easyblock.py b/easybuild/framework/easyblock.py index 843c515c94..0018bb8334 100644 --- a/easybuild/framework/easyblock.py +++ b/easybuild/framework/easyblock.py @@ -1411,6 +1411,13 @@ def make_module_extra(self, altroot=None, altversion=None): if not modloadmsg.endswith('\n'): modloadmsg += '\n' lines.append(self.module_generator.msg_on_load(modloadmsg)) + + modunloadmsg = self.cfg['modunloadmsg'] + if modunloadmsg: + # add trailing newline to prevent that shell prompt is 'glued' to module unload/purge message + if not modunloadmsg.endswith('\n'): + modunloadmsg += '\n' + lines.append(self.module_generator.msg_on_unload(modunloadmsg)) for (key, value) in self.cfg['modaliases'].items(): lines.append(self.module_generator.set_alias(key, value)) diff --git a/easybuild/framework/easyconfig/default.py b/easybuild/framework/easyconfig/default.py index 680a56d84e..b37c3660f0 100644 --- a/easybuild/framework/easyconfig/default.py +++ b/easybuild/framework/easyconfig/default.py @@ -195,6 +195,7 @@ 'modextrapaths': [{}, "Extra paths to be prepended in module file", MODULES], 'modextravars': [{}, "Extra environment variables to be added to module file", MODULES], 'modloadmsg': [{}, "Message that should be printed when generated module is loaded", MODULES], + 'modunloadmsg': [{}, "Message that should be printed when generated module is unloaded", MODULES], 'modluafooter': ["", "Footer to include in generated module file (Lua syntax)", MODULES], 'modaltsoftname': [None, "Module name to use (rather than using software name", MODULES], 'modtclfooter': ["", "Footer to include in generated module file (Tcl syntax)", MODULES], diff --git a/easybuild/tools/module_generator.py b/easybuild/tools/module_generator.py index 6b3c292584..8fa40f63ab 100644 --- a/easybuild/tools/module_generator.py +++ b/easybuild/tools/module_generator.py @@ -502,6 +502,12 @@ def msg_on_load(self, msg): """ raise NotImplementedError + def msg_on_unload(self, msg): + """ + Add a message that should be printed when unloading the module. + """ + raise NotImplementedError + def set_alias(self, key, value): """ Generate set-alias statement in modulefile for the given key/value pair. @@ -950,6 +956,15 @@ def msg_on_load(self, msg): msg = re.sub(r'((?= 7.7.38) diff --git a/test/framework/easyconfig.py b/test/framework/easyconfig.py index 51f9001b91..f09a0896a6 100644 --- a/test/framework/easyconfig.py +++ b/test/framework/easyconfig.py @@ -1100,6 +1100,13 @@ def test_templating_constants(self): 'Perl: %%(perlver)s, %%(perlmajver)s, %%(perlminver)s, %%(perlshortver)s', 'R: %%(rver)s, %%(rmajver)s, %%(rminver)s, %%(rshortver)s', ]), + 'modunloadmsg = "%s"' % '; '.join([ + 'CUDA: %%(cudaver)s, %%(cudamajver)s, %%(cudaminver)s, %%(cudashortver)s', + 'Java: %%(javaver)s, %%(javamajver)s, %%(javaminver)s, %%(javashortver)s', + 'Python: %%(pyver)s, %%(pymajver)s, %%(pyminver)s, %%(pyshortver)s', + 'Perl: %%(perlver)s, %%(perlmajver)s, %%(perlminver)s, %%(perlshortver)s', + 'R: %%(rver)s, %%(rmajver)s, %%(rminver)s, %%(rshortver)s', + ]), 'modextrapaths = {"PI_MOD_NAME": "%%(module_name)s"}', 'license_file = HOME + "/licenses/PI/license.txt"', "github_account = 'easybuilders'", @@ -1139,6 +1146,7 @@ def test_templating_constants(self): "Perl: 5.22.0, 5, 22, 5.22; " "R: 3.2.3, 3, 2, 3.2") self.assertEqual(ec['modloadmsg'], expected) + self.assertEqual(ec['modunloadmsg'], expected) self.assertEqual(ec['modextrapaths'], {'PI_MOD_NAME': 'PI/3.04-Python-2.7.10'}) self.assertEqual(ec['license_file'], os.path.join(os.environ['HOME'], 'licenses', 'PI', 'license.txt')) @@ -1225,6 +1233,7 @@ def test_java_wrapper_templating(self): 'toolchain = {"name":"GCC", "version": "4.6.3"}', 'dependencies = [("Java", "11", "", SYSTEM)]', 'modloadmsg = "Java: %(javaver)s, %(javamajver)s, %(javashortver)s"', + 'modunloadmsg = "Java: %(javaver)s, %(javamajver)s, %(javashortver)s"', ]) self.prep() eb = EasyConfig(self.eb_file) @@ -1236,6 +1245,7 @@ def test_java_wrapper_templating(self): self.assertNotIn('javaminver', eb.template_values) self.assertEqual(eb['modloadmsg'], "Java: 11, 11, 11") + self.assertEqual(eb['modunloadmsg'], "Java: 11, 11, 11") def test_python_whl_templating(self): """test templating for Python wheels""" diff --git a/test/framework/module_generator.py b/test/framework/module_generator.py index 450388275b..285f0a6cea 100644 --- a/test/framework/module_generator.py +++ b/test/framework/module_generator.py @@ -1097,6 +1097,36 @@ def test_load_msg(self): ]) self.assertEqual(lua_load_msg, self.modgen.msg_on_load('test $test \\$test\ntest $foo \\$bar')) + def test_unload_msg(self): + """Test including an unload message in the module file.""" + if self.MODULE_GENERATOR_CLASS == ModuleGeneratorTcl: + expected = "\nif { [ module-info mode unload ] } {\nputs stderr \"test\"\n}\n" + self.assertEqual(expected, self.modgen.msg_on_unload('test')) + + tcl_unload_msg = '\n'.join([ + '', + "if { [ module-info mode unload ] } {", + "puts stderr \"test \\$test \\$test", + "test \\$foo \\$bar\"", + "}", + '', + ]) + self.assertEqual(tcl_unload_msg, self.modgen.msg_on_unload('test $test \\$test\ntest $foo \\$bar')) + + else: + expected = '\nif mode() == "unload" then\nio.stderr:write([==[test]==])\nend\n' + self.assertEqual(expected, self.modgen.msg_on_unload('test')) + + lua_unload_msg = '\n'.join([ + '', + 'if mode() == "unload" then', + 'io.stderr:write([==[test $test \\$test', + 'test $foo \\$bar]==])', + 'end', + '', + ]) + self.assertEqual(lua_unload_msg, self.modgen.msg_on_unload('test $test \\$test\ntest $foo \\$bar')) + def test_module_naming_scheme(self): """Test using default module naming scheme.""" all_stops = [x[0] for x in EasyBlock.get_steps()] From de8f3fc8f4cc95ef88a4ec97c57dda993193d684 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20Jos=C3=A9=20Gonz=C3=A1lez=20Carrillo?= Date: Thu, 9 Mar 2023 18:51:26 +0100 Subject: [PATCH 2/2] Remove whitespaces in blank lines --- easybuild/framework/easyblock.py | 2 +- easybuild/tools/module_generator.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/easybuild/framework/easyblock.py b/easybuild/framework/easyblock.py index 0018bb8334..1d177eafb9 100644 --- a/easybuild/framework/easyblock.py +++ b/easybuild/framework/easyblock.py @@ -1411,7 +1411,7 @@ def make_module_extra(self, altroot=None, altversion=None): if not modloadmsg.endswith('\n'): modloadmsg += '\n' lines.append(self.module_generator.msg_on_load(modloadmsg)) - + modunloadmsg = self.cfg['modunloadmsg'] if modunloadmsg: # add trailing newline to prevent that shell prompt is 'glued' to module unload/purge message diff --git a/easybuild/tools/module_generator.py b/easybuild/tools/module_generator.py index 8fa40f63ab..33ff4659d4 100644 --- a/easybuild/tools/module_generator.py +++ b/easybuild/tools/module_generator.py @@ -956,7 +956,7 @@ def msg_on_load(self, msg): msg = re.sub(r'((?