-
Notifications
You must be signed in to change notification settings - Fork 217
support depends_on "load" statements in generated modules via --module-depends-on and module_depends_on easyconfig parameter #2391
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
Changes from 9 commits
6f21c8f
fcb0e21
800bd90
63bda19
acf8cd1
2d9166a
8e02128
5e29702
279e4a3
631810d
4b1c65e
84094e8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -236,6 +236,7 @@ def mk_full_default_path(name, prefix=DEFAULT_PREFIX): | |
| False: [ | ||
| 'dry_run', | ||
| 'recursive_mod_unload', | ||
| 'mod_use_depends_on', | ||
| 'retain_all_deps', | ||
| 'silent', | ||
| 'try_to_generate', | ||
|
|
@@ -386,6 +387,7 @@ def init_build_options(build_options=None, cmdline_options=None): | |
| 'check_osdeps': not cmdline_options.ignore_osdeps, | ||
| 'dry_run': cmdline_options.dry_run or cmdline_options.dry_run_short, | ||
| 'recursive_mod_unload': cmdline_options.recursive_module_unload, | ||
| 'mod_use_depends_on': cmdline_options.module_use_depends_on, | ||
|
||
| 'retain_all_deps': retain_all_deps, | ||
| 'validate': not cmdline_options.force, | ||
| 'valid_module_classes': module_classes(), | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -403,8 +403,9 @@ class ModuleGeneratorTcl(ModuleGenerator): | |
| MODULE_SHEBANG = '#%Module' | ||
| CHARS_TO_ESCAPE = ['$'] | ||
|
|
||
| LOAD_REGEX = r"^\s*module\s+load\s+(\S+)" | ||
| LOAD_REGEX = r"^\s*module\s+(?:load|depends-on)\s+(\S+)" | ||
| LOAD_TEMPLATE = "module load %(mod_name)s" | ||
| LOAD_TEMPLATE_DEPENDS_ON = "depends-on %(mod_name)s" | ||
|
|
||
| def check_group(self, group, error_msg=None): | ||
| """ | ||
|
|
@@ -494,7 +495,7 @@ def getenv_cmd(self, envvar): | |
| """ | ||
| return '$env(%s)' % envvar | ||
|
|
||
| def load_module(self, mod_name, recursive_unload=False, unload_modules=None): | ||
| def load_module(self, mod_name, recursive_unload=False, use_depends_on=False, unload_modules=None): | ||
| """ | ||
| Generate load statement for specified module. | ||
|
|
||
|
|
@@ -505,9 +506,16 @@ def load_module(self, mod_name, recursive_unload=False, unload_modules=None): | |
| body = [] | ||
| if unload_modules: | ||
| body.extend([self.unload_module(m).strip() for m in unload_modules]) | ||
| body.append(self.LOAD_TEMPLATE) | ||
|
|
||
| if build_option('recursive_mod_unload') or recursive_unload: | ||
| load_template = self.LOAD_TEMPLATE | ||
| # Lmod 7.6.1+ supports depends-on which does this most nicely: | ||
| if build_option('mod_use_depends_on') or use_depends_on: | ||
| if not modules_tool().supports_depends_on: | ||
| raise EasyBuildError("depends_on statements in generated module are not supported by modules tool") | ||
| load_template = self.LOAD_TEMPLATE_DEPENDS_ON | ||
| body.append(load_template) | ||
|
|
||
| if (build_option('recursive_mod_unload') or recursive_unload or | ||
| load_template == self.LOAD_TEMPLATE_DEPENDS_ON): | ||
|
||
| # not wrapping the 'module load' with an is-loaded guard ensures recursive unloading; | ||
| # when "module unload" is called on the module in which the dependency "module load" is present, | ||
| # it will get translated to "module unload" | ||
|
|
@@ -668,8 +676,9 @@ class ModuleGeneratorLua(ModuleGenerator): | |
| MODULE_SHEBANG = '' # no 'shebang' in Lua module files | ||
| CHARS_TO_ESCAPE = [] | ||
|
|
||
| LOAD_REGEX = r'^\s*load\("(\S+)"' | ||
| LOAD_REGEX = r'^\s*(?:load|depends_on)\("(\S+)"' | ||
| LOAD_TEMPLATE = 'load("%(mod_name)s")' | ||
| LOAD_TEMPLATE_DEPENDS_ON = 'depends_on("%(mod_name)s")' | ||
|
|
||
| PATH_JOIN_TEMPLATE = 'pathJoin(root, "%s")' | ||
| UPDATE_PATH_TEMPLATE = '%s_path("%s", %s)' | ||
|
|
@@ -784,7 +793,7 @@ def getenv_cmd(self, envvar): | |
| """ | ||
| return 'os.getenv("%s")' % envvar | ||
|
|
||
| def load_module(self, mod_name, recursive_unload=False, unload_modules=None): | ||
| def load_module(self, mod_name, recursive_unload=False, use_depends_on=False, unload_modules=None): | ||
| """ | ||
| Generate load statement for specified module. | ||
|
|
||
|
|
@@ -795,19 +804,29 @@ def load_module(self, mod_name, recursive_unload=False, unload_modules=None): | |
| body = [] | ||
| if unload_modules: | ||
| body.extend([self.unload_module(m).strip() for m in unload_modules]) | ||
| body.append(self.LOAD_TEMPLATE) | ||
|
|
||
| if build_option('recursive_mod_unload') or recursive_unload: | ||
| # wrapping the 'module load' with an 'is-loaded or mode == unload' | ||
| # guard ensures recursive unloading while avoiding load storms, | ||
| # when "module unload" is called on the module in which the | ||
| # depedency "module load" is present, it will get translated | ||
| # to "module unload" | ||
| # see also http://lmod.readthedocs.io/en/latest/210_load_storms.html | ||
| load_guard = 'isloaded("%(mod_name)s") or mode() == "unload"' | ||
|
|
||
| load_template = self.LOAD_TEMPLATE | ||
| # Lmod 7.6+ supports depends_on which does this most nicely: | ||
| if build_option('mod_use_depends_on') or use_depends_on: | ||
| if not modules_tool().supports_depends_on: | ||
| raise EasyBuildError("depends_on statements in generated module are not supported by modules tool") | ||
| load_template = self.LOAD_TEMPLATE_DEPENDS_ON | ||
|
|
||
| body.append(load_template) | ||
| if load_template == self.LOAD_TEMPLATE_DEPENDS_ON: | ||
| load_statement = body + [''] | ||
| else: | ||
| load_guard = 'isloaded("%(mod_name)s")' | ||
| load_statement = [self.conditional_statement(load_guard, '\n'.join(body), negative=True)] | ||
| if build_option('recursive_mod_unload') or recursive_unload: | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. make this
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, it really needs to be
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK, I overlooked that indeed, thanks or clarifying |
||
| # wrapping the 'module load' with an 'is-loaded or mode == unload' | ||
| # guard ensures recursive unloading while avoiding load storms, | ||
| # when "module unload" is called on the module in which the | ||
| # depedency "module load" is present, it will get translated | ||
| # to "module unload" | ||
| # see also http://lmod.readthedocs.io/en/latest/210_load_storms.html | ||
| load_guard = 'isloaded("%(mod_name)s") or mode() == "unload"' | ||
| else: | ||
| load_guard = 'isloaded("%(mod_name)s")' | ||
| load_statement = [self.conditional_statement(load_guard, '\n'.join(body), negative=True)] | ||
|
|
||
| return '\n'.join([''] + load_statement) % {'mod_name': mod_name} | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -456,6 +456,9 @@ def config_options(self): | |
| 'module-naming-scheme': ("Module naming scheme to use", None, 'store', DEFAULT_MNS), | ||
| 'module-syntax': ("Syntax to be used for module files", 'choice', 'store', DEFAULT_MODULE_SYNTAX, | ||
| sorted(avail_module_generators().keys())), | ||
| 'module-use-depends-on': ("Use depends_on (Lmod 7.6.1+) for dependencies in all generated modules " | ||
|
||
| "(implies recursive unloading of modules).", | ||
| None, 'store_true', False), | ||
| 'moduleclasses': (("Extend supported module classes " | ||
| "(For more info on the default classes, use --show-default-moduleclasses)"), | ||
| 'strlist', 'extend', [x[0] for x in DEFAULT_MODULECLASSES]), | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -258,6 +258,17 @@ def test_load(self): | |
|
|
||
| init_config(build_options={'recursive_mod_unload': True}) | ||
| self.assertEqual(expected, self.modgen.load_module("mod_name")) | ||
|
|
||
| # Lmod 7.6+ depends-on | ||
| if self.modtool.supports_depends_on: | ||
| expected = '\n'.join([ | ||
| '', | ||
| "depends-on mod_name", | ||
| '', | ||
| ]) | ||
| self.assertEqual(expected, self.modgen.load_module("mod_name", use_depends_on=True)) | ||
| init_config(build_options={'mod_use_depends_on': 'True'}) | ||
| self.assertEqual(expected, self.modgen.load_module("mod_name")) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. also check the other case, with |
||
| else: | ||
| # default: guarded module load (which implies no recursive unloading) | ||
| expected = '\n'.join([ | ||
|
|
@@ -283,6 +294,17 @@ def test_load(self): | |
| init_config(build_options={'recursive_mod_unload': True}) | ||
| self.assertEqual(expected, self.modgen.load_module("mod_name")) | ||
|
|
||
| # Lmod 7.6+ depends_on | ||
| if self.modtool.supports_depends_on: | ||
| expected = '\n'.join([ | ||
| '', | ||
| 'depends_on("mod_name")', | ||
| '', | ||
| ]) | ||
| self.assertEqual(expected, self.modgen.load_module("mod_name", use_depends_on=True)) | ||
| init_config(build_options={'mod_use_depends_on': 'True'}) | ||
| self.assertEqual(expected, self.modgen.load_module("mod_name")) | ||
|
|
||
| def test_unload(self): | ||
| """Test unload part in generated module file.""" | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bartoldeman I would avoid
module_use, since that has a particular meaning (not at all related todepends_on).How about
module_depends_onoruse_depends_on?