-
Notifications
You must be signed in to change notification settings - Fork 203
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
Allow user-local modules with hierarchical naming schemes #1472
Changes from all commits
b0bdb17
67c39ec
2335cce
60ea159
7562542
9bd6a1e
df718d0
3e3d19c
db102a4
26c9061
a647c1e
9c8a093
6168a58
99e9a61
c412d83
9b86106
b2570bd
352e936
2a74925
de3b55d
ce1aed5
9d08d07
c862e4e
e43787e
3506ee1
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 |
---|---|---|
|
@@ -128,6 +128,12 @@ def conditional_statement(self, condition, body, negative=False): | |
"""Return formatted conditional statement, with given condition and body.""" | ||
raise NotImplementedError | ||
|
||
def getenv_cmd(self, envvar): | ||
""" | ||
Return module-syntax specific code to get value of specific environment variable. | ||
""" | ||
raise NotImplementedError | ||
|
||
def load_module(self, mod_name, recursive_unload=False, unload_modules=None): | ||
""" | ||
Generate load statement for specified module. | ||
|
@@ -286,13 +292,26 @@ def prepend_paths(self, key, paths, allow_abs=False, expand_relpaths=True): | |
statements = [template % (key, p) for p in abspaths] | ||
return ''.join(statements) | ||
|
||
def use(self, paths): | ||
def use(self, paths, prefix=None, guarded=False): | ||
""" | ||
Generate module use statements for given list of module paths. | ||
@param paths: list of module path extensions to generate use statements for; paths will be quoted | ||
@param prefix: optional path prefix; not quoted, i.e., can be a statement | ||
@param guarded: use statements will be guarded to only apply if path exists | ||
""" | ||
use_statements = [] | ||
for path in paths: | ||
use_statements.append("module use %s\n" % path) | ||
quoted_path = quote_str(path) | ||
if prefix: | ||
full_path = '[ file join %s %s ]' % (prefix, quoted_path) | ||
else: | ||
full_path = quoted_path | ||
if guarded: | ||
cond_statement = self.conditional_statement('file isdirectory %s' % full_path, | ||
'module use %s' % full_path) | ||
use_statements.append(cond_statement) | ||
else: | ||
use_statements.append("module use %s\n" % full_path) | ||
return ''.join(use_statements) | ||
|
||
def set_environment(self, key, value, relpath=False): | ||
|
@@ -325,6 +344,12 @@ def set_alias(self, key, value): | |
# quotes are needed, to ensure smooth working of EBDEVEL* modulefiles | ||
return 'set-alias\t%s\t\t%s\n' % (key, quote_str(value)) | ||
|
||
def getenv_cmd(self, envvar): | ||
""" | ||
Return module-syntax specific code to get value of specific environment variable. | ||
""" | ||
return '$env(%s)' % envvar | ||
|
||
|
||
class ModuleGeneratorLua(ModuleGenerator): | ||
""" | ||
|
@@ -339,7 +364,7 @@ class ModuleGeneratorLua(ModuleGenerator): | |
LOAD_TEMPLATE = 'load("%(mod_name)s")' | ||
|
||
PATH_JOIN_TEMPLATE = 'pathJoin(root, "%s")' | ||
PREPEND_PATH_TEMPLATE = 'prepend_path("%s", %s)\n' | ||
PREPEND_PATH_TEMPLATE = 'prepend_path("%s", %s)' | ||
|
||
def __init__(self, *args, **kwargs): | ||
"""ModuleGeneratorLua constructor.""" | ||
|
@@ -462,14 +487,30 @@ def prepend_paths(self, key, paths, allow_abs=False, expand_relpaths=True): | |
abspaths.append('root') | ||
|
||
statements = [self.PREPEND_PATH_TEMPLATE % (key, p) for p in abspaths] | ||
return ''.join(statements) | ||
statements.append('') | ||
return '\n'.join(statements) | ||
|
||
def use(self, paths): | ||
def use(self, paths, prefix=None, guarded=False): | ||
""" | ||
Generate module use statements for given list of module paths. | ||
@param paths: list of module path extensions to generate use statements for | ||
@param paths: list of module path extensions to generate use statements for; paths will be quoted | ||
@param prefix: optional path prefix; not quoted, i.e., can be a statement | ||
@param guarded: use statements will be guarded to only apply if path exists | ||
""" | ||
return ''.join([self.PREPEND_PATH_TEMPLATE % ('MODULEPATH', quote_str(p)) for p in paths]) | ||
use_statements = [] | ||
for path in paths: | ||
quoted_path = quote_str(path) | ||
if prefix: | ||
full_path = 'pathJoin(%s, %s)' % (prefix, quoted_path) | ||
else: | ||
full_path = quoted_path | ||
if guarded: | ||
cond_statement = self.conditional_statement('isDir(%s)' % full_path, | ||
self.PREPEND_PATH_TEMPLATE % ('MODULEPATH', full_path)) | ||
use_statements.append(cond_statement) | ||
else: | ||
use_statements.append(self.PREPEND_PATH_TEMPLATE % ('MODULEPATH', full_path) + '\n') | ||
return ''.join(use_statements) | ||
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.
|
||
|
||
def set_environment(self, key, value, relpath=False): | ||
""" | ||
|
@@ -497,6 +538,12 @@ def set_alias(self, key, value): | |
# quotes are needed, to ensure smooth working of EBDEVEL* modulefiles | ||
return 'setalias("%s", %s)\n' % (key, quote_str(value)) | ||
|
||
def getenv_cmd(self, envvar): | ||
""" | ||
Return module-syntax specific code to get value of specific environment variable. | ||
""" | ||
return 'os.getenv("%s")' % envvar | ||
|
||
|
||
def avail_module_generators(): | ||
""" | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -83,6 +83,17 @@ def det_modpath_extensions(self, ec): | |
|
||
return self.categorize_paths(basepaths) | ||
|
||
def det_user_modpath_extensions(self, ec): | ||
""" | ||
Determine user module path extensions, if any. As typical users are not expected to have many local modules, | ||
further categorizing them using module classes is considered overkill. Thus, we are using a plain hierarchical | ||
scheme for user modules instead. | ||
|
||
Examples: Compiler/GCC/4.8.3 (for GCC/4.8.3 module), MPI/GCC/4.8.3/OpenMPI/1.6.5 (for OpenMPI/1.6.5 module) | ||
""" | ||
# Use "system" module path extensions of hierarchical MNS (i.e., w/o module class) | ||
return super(CategorizedHMNS, self).det_modpath_extensions(ec) | ||
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. this is exactly the same as the default implementation? what's the point of defining it then, just let inheritance take care of it? 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. It is called because of inheritance. 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, maybe make that clear with a comment in the code? |
||
|
||
def det_init_modulepaths(self, ec): | ||
""" | ||
Determine list of initial module paths (i.e., top of the hierarchy). | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -126,6 +126,18 @@ def det_modpath_extensions(self, ec): | |
# by default: an empty list of subdirectories to extend $MODULEPATH with | ||
return [] | ||
|
||
def det_user_modpath_extensions(self, ec): | ||
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. @geimer @boegel This does not seem to be respecting
Notice the missing 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. @ocaisa what was the full EasyBuild configuration here ( 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.
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. I get the same effect with using 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. This occurs with a vanilla instance and the command line:
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. fix implemented in #2250 |
||
""" | ||
Determine list of subdirectories relative to the user-specific modules directory for which to extend | ||
$MODULEPATH with when this module is loaded (if any). | ||
|
||
@param ec: dict-like object with easyconfig parameter values; for now only the 'name', | ||
'version', 'versionsuffix' and 'toolchain' parameters are guaranteed to be available | ||
@return: A list of $MODULEPATH subdirectories. | ||
""" | ||
# by default: use "system" module path extensions of naming scheme | ||
return self.det_modpath_extensions(ec) | ||
|
||
def det_init_modulepaths(self, ec): | ||
""" | ||
Determine initial module paths, where the modules that are top of the hierarchy (if any) live. | ||
|
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.
use
'\n'.join
here, and don't include\n
everywhere above