Skip to content

Commit eeb290f

Browse files
authored
Merge pull request #4687 from Micket/modulesep
Allow use of custom delimiter for paths in module generator
2 parents 6fcfe97 + 6034b20 commit eeb290f

File tree

3 files changed

+78
-41
lines changed

3 files changed

+78
-41
lines changed

easybuild/framework/easyblock.py

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1469,22 +1469,27 @@ def make_module_extra(self, altroot=None, altversion=None):
14691469
for (key, value) in self.cfg['modextravars'].items():
14701470
lines.append(self.module_generator.set_environment(key, value))
14711471

1472-
for (key, value) in self.cfg['modextrapaths'].items():
1473-
if isinstance(value, str):
1474-
value = [value]
1475-
elif not isinstance(value, (tuple, list)):
1476-
raise EasyBuildError("modextrapaths dict value %s (type: %s) is not a list or tuple",
1477-
value, type(value))
1478-
lines.append(self.module_generator.prepend_paths(key, value, allow_abs=self.cfg['allow_prepend_abs_path']))
1479-
1480-
for (key, value) in self.cfg['modextrapaths_append'].items():
1481-
if isinstance(value, str):
1482-
value = [value]
1483-
elif not isinstance(value, (tuple, list)):
1484-
raise EasyBuildError("modextrapaths_append dict value %s (type: %s) is not a list or tuple",
1485-
value, type(value))
1486-
lines.append(self.module_generator.append_paths(key, value, allow_abs=self.cfg['allow_append_abs_path']))
1472+
for extrapaths_type, prepend in [('modextrapaths', True), ('modextrapaths_append', False)]:
1473+
allow_abs = self.cfg['allow_prepend_abs_path'] if prepend else self.cfg['allow_append_abs_path']
14871474

1475+
for (key, value) in self.cfg[extrapaths_type].items():
1476+
if not isinstance(value, (tuple, list, dict, str)):
1477+
raise EasyBuildError(
1478+
f"{extrapaths_type} dict value '{value}' (type {type(value)}) is not a 'list, dict or str'"
1479+
)
1480+
1481+
try:
1482+
paths = value['paths']
1483+
delim = value['delimiter']
1484+
except KeyError:
1485+
raise EasyBuildError(f'{extrapaths_type} dict "{value}" lacks "paths" or "delimiter" items')
1486+
except TypeError:
1487+
paths = value
1488+
delim = ':'
1489+
1490+
lines.append(
1491+
self.module_generator.update_paths(key, paths, prepend=prepend, delim=delim, allow_abs=allow_abs)
1492+
)
14881493
# add lines to update $PYTHONPATH or $EBPYTHONPREFIXES
14891494
lines.extend(self.make_module_pythonpath())
14901495

easybuild/tools/module_generator.py

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -235,33 +235,37 @@ def _filter_paths(self, key, paths):
235235
filtered_paths = None
236236
return filtered_paths
237237

238-
def append_paths(self, key, paths, allow_abs=False, expand_relpaths=True):
238+
def append_paths(self, key, paths, allow_abs=False, expand_relpaths=True, delim=':'):
239239
"""
240240
Generate append-path statements for the given list of paths.
241241
242242
:param key: environment variable to append paths to
243243
:param paths: list of paths to append
244244
:param allow_abs: allow providing of absolute paths
245245
:param expand_relpaths: expand relative paths into absolute paths (by prefixing install dir)
246+
:param delim: delimiter used between paths
246247
"""
247248
paths = self._filter_paths(key, paths)
248249
if paths is None:
249250
return ''
250-
return self.update_paths(key, paths, prepend=False, allow_abs=allow_abs, expand_relpaths=expand_relpaths)
251+
return self.update_paths(key, paths, prepend=False, allow_abs=allow_abs, expand_relpaths=expand_relpaths,
252+
delim=delim)
251253

252-
def prepend_paths(self, key, paths, allow_abs=False, expand_relpaths=True):
254+
def prepend_paths(self, key, paths, allow_abs=False, expand_relpaths=True, delim=':'):
253255
"""
254256
Generate prepend-path statements for the given list of paths.
255257
256258
:param key: environment variable to append paths to
257259
:param paths: list of paths to append
258260
:param allow_abs: allow providing of absolute paths
259261
:param expand_relpaths: expand relative paths into absolute paths (by prefixing install dir)
262+
:param delim: delimiter used between paths
260263
"""
261264
paths = self._filter_paths(key, paths)
262265
if paths is None:
263266
return ''
264-
return self.update_paths(key, paths, prepend=True, allow_abs=allow_abs, expand_relpaths=expand_relpaths)
267+
return self.update_paths(key, paths, prepend=True, allow_abs=allow_abs, expand_relpaths=expand_relpaths,
268+
delim=delim)
265269

266270
def _modulerc_check_module_version(self, module_version):
267271
"""
@@ -552,15 +556,16 @@ def unload_module(self, mod_name):
552556
"""
553557
raise NotImplementedError
554558

555-
def update_paths(self, key, paths, prepend=True, allow_abs=False, expand_relpaths=True):
559+
def update_paths(self, key, paths, prepend=True, allow_abs=False, expand_relpaths=True, delim=':'):
556560
"""
557561
Generate prepend-path or append-path statements for the given list of paths.
558562
559563
:param key: environment variable to prepend/append paths to
560-
:param paths: list of paths to prepend
564+
:param paths: list of paths to prepend/append
561565
:param prepend: whether to prepend (True) or append (False) paths
562566
:param allow_abs: allow providing of absolute paths
563567
:param expand_relpaths: expand relative paths into absolute paths (by prefixing install dir)
568+
:param delim: delimiter used between paths
564569
"""
565570
raise NotImplementedError
566571

@@ -970,15 +975,16 @@ def msg_on_unload(self, msg):
970975
print_cmd = "puts stderr %s" % quote_str(msg, tcl=True)
971976
return '\n'.join(['', self.conditional_statement("module-info mode unload", print_cmd, indent=False)])
972977

973-
def update_paths(self, key, paths, prepend=True, allow_abs=False, expand_relpaths=True):
978+
def update_paths(self, key, paths, prepend=True, allow_abs=False, expand_relpaths=True, delim=':'):
974979
"""
975980
Generate prepend-path or append-path statements for the given list of paths.
976981
977982
:param key: environment variable to prepend/append paths to
978-
:param paths: list of paths to prepend
983+
:param paths: list of paths to prepend/append
979984
:param prepend: whether to prepend (True) or append (False) paths
980985
:param allow_abs: allow providing of absolute paths
981986
:param expand_relpaths: expand relative paths into absolute paths (by prefixing install dir)
987+
:param delim: delimiter used between paths
982988
"""
983989
if prepend:
984990
update_type = 'prepend'
@@ -1010,7 +1016,8 @@ def update_paths(self, key, paths, prepend=True, allow_abs=False, expand_relpath
10101016
else:
10111017
abspaths.append(path)
10121018

1013-
statements = ['%s-path\t%s\t\t%s\n' % (update_type, key, p) for p in abspaths]
1019+
delim_opt = '' if delim == ':' else f' -d "{delim}"'
1020+
statements = [f'{update_type}-path{delim_opt}\t{key}\t\t{p}\n' for p in abspaths]
10141021
return ''.join(statements)
10151022

10161023
def set_alias(self, key, value):
@@ -1161,6 +1168,7 @@ class ModuleGeneratorLua(ModuleGenerator):
11611168

11621169
PATH_JOIN_TEMPLATE = 'pathJoin(root, "%s")'
11631170
UPDATE_PATH_TEMPLATE = '%s_path("%s", %s)'
1171+
UPDATE_PATH_TEMPLATE_DELIM = '%s_path("%s", %s, "%s")'
11641172

11651173
START_STR = '[==['
11661174
END_STR = ']==]'
@@ -1422,7 +1430,7 @@ def modulerc(self, module_version=None, filepath=None, modulerc_txt=None):
14221430
return super(ModuleGeneratorLua, self).modulerc(module_version=module_version, filepath=filepath,
14231431
modulerc_txt=modulerc_txt)
14241432

1425-
def update_paths(self, key, paths, prepend=True, allow_abs=False, expand_relpaths=True):
1433+
def update_paths(self, key, paths, prepend=True, allow_abs=False, expand_relpaths=True, delim=':'):
14261434
"""
14271435
Generate prepend_path or append_path statements for the given list of paths
14281436
@@ -1431,6 +1439,7 @@ def update_paths(self, key, paths, prepend=True, allow_abs=False, expand_relpath
14311439
:param prepend: whether to prepend (True) or append (False) paths
14321440
:param allow_abs: allow providing of absolute paths
14331441
:param expand_relpaths: expand relative paths into absolute paths (by prefixing install dir)
1442+
:param delim: delimiter used between paths
14341443
"""
14351444
if prepend:
14361445
update_type = 'prepend'
@@ -1463,7 +1472,10 @@ def update_paths(self, key, paths, prepend=True, allow_abs=False, expand_relpath
14631472
else:
14641473
abspaths.append('root')
14651474

1466-
statements = [self.UPDATE_PATH_TEMPLATE % (update_type, key, p) for p in abspaths]
1475+
if delim != ':':
1476+
statements = [self.UPDATE_PATH_TEMPLATE_DELIM % (update_type, key, p, delim) for p in abspaths]
1477+
else:
1478+
statements = [self.UPDATE_PATH_TEMPLATE % (update_type, key, p) for p in abspaths]
14671479
statements.append('')
14681480
return '\n'.join(statements)
14691481

test/framework/easyblock.py

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1259,6 +1259,7 @@ def test_make_module_step(self):
12591259
modextrapaths = {
12601260
'PATH': ('xbin', 'pibin'),
12611261
'CPATH': 'pi/include',
1262+
'TCLLIBPATH': {'paths': 'pi', 'delimiter': ' '},
12621263
}
12631264
modextrapaths_append = {'APPEND_PATH': 'append_path'}
12641265
self.contents = '\n'.join([
@@ -1333,28 +1334,47 @@ def test_make_module_step(self):
13331334
self.assertTrue(regex.search(txt), "Pattern %s found in %s" % (regex.pattern, txt))
13341335

13351336
for (key, vals) in modextrapaths.items():
1336-
if isinstance(vals, str):
1337-
vals = [vals]
1338-
for val in vals:
1339-
if get_module_syntax() == 'Tcl':
1340-
regex = re.compile(r'^prepend-path\s+%s\s+\$root/%s$' % (key, val), re.M)
1341-
elif get_module_syntax() == 'Lua':
1342-
regex = re.compile(r'^prepend_path\("%s", pathJoin\(root, "%s"\)\)$' % (key, val), re.M)
1343-
else:
1344-
self.fail("Unknown module syntax: %s" % get_module_syntax())
1345-
self.assertTrue(regex.search(txt), "Pattern %s found in %s" % (regex.pattern, txt))
1346-
# Check for duplicates
1347-
num_prepends = len(regex.findall(txt))
1348-
self.assertEqual(num_prepends, 1, "Expected exactly 1 %s command in %s" % (regex.pattern, txt))
1337+
if isinstance(vals, dict):
1338+
delim = vals['delimiter']
1339+
paths = vals['paths']
1340+
if isinstance(paths, str):
1341+
paths = [paths]
1342+
1343+
for val in paths:
1344+
if get_module_syntax() == 'Tcl':
1345+
regex = re.compile(fr'^prepend-path\s+-d\s+"{delim}"\s+{key}\s+\$root/{val}$', re.M)
1346+
elif get_module_syntax() == 'Lua':
1347+
regex = re.compile(fr'^prepend_path\("{key}", pathJoin\(root, "{val}"\), "{delim}"\)$', re.M)
1348+
else:
1349+
self.fail("Unknown module syntax: %s" % get_module_syntax())
1350+
self.assertTrue(regex.search(txt), "Pattern %s found in %s" % (regex.pattern, txt))
1351+
# Check for duplicates
1352+
num_prepends = len(regex.findall(txt))
1353+
self.assertEqual(num_prepends, 1, "Expected exactly 1 %s command in %s" % (regex.pattern, txt))
1354+
else:
1355+
if isinstance(vals, str):
1356+
vals = [vals]
1357+
1358+
for val in vals:
1359+
if get_module_syntax() == 'Tcl':
1360+
regex = re.compile(fr'^prepend-path\s+{key}\s+\$root/{val}$', re.M)
1361+
elif get_module_syntax() == 'Lua':
1362+
regex = re.compile(fr'^prepend_path\("{key}", pathJoin\(root, "{val}"\)\)$', re.M)
1363+
else:
1364+
self.fail("Unknown module syntax: %s" % get_module_syntax())
1365+
self.assertTrue(regex.search(txt), "Pattern %s found in %s" % (regex.pattern, txt))
1366+
# Check for duplicates
1367+
num_prepends = len(regex.findall(txt))
1368+
self.assertEqual(num_prepends, 1, "Expected exactly 1 %s command in %s" % (regex.pattern, txt))
13491369

13501370
for (key, vals) in modextrapaths_append.items():
13511371
if isinstance(vals, str):
13521372
vals = [vals]
13531373
for val in vals:
13541374
if get_module_syntax() == 'Tcl':
1355-
regex = re.compile(r'^append-path\s+%s\s+\$root/%s$' % (key, val), re.M)
1375+
regex = re.compile(r'^append-path\s+(-d ".")?%s\s+\$root/%s$' % (key, val), re.M)
13561376
elif get_module_syntax() == 'Lua':
1357-
regex = re.compile(r'^append_path\("%s", pathJoin\(root, "%s"\)\)$' % (key, val), re.M)
1377+
regex = re.compile(r'^append_path\("%s", pathJoin\(root, "%s"\)(, ".")?\)$' % (key, val), re.M)
13581378
else:
13591379
self.fail("Unknown module syntax: %s" % get_module_syntax())
13601380
self.assertTrue(regex.search(txt), "Pattern %s found in %s" % (regex.pattern, txt))

0 commit comments

Comments
 (0)