Skip to content

Commit 6db0a64

Browse files
authored
Merge pull request #4686 from Flamefire/patch-1
simplify code for determining the PYTHONPATH module entries
2 parents eeb290f + 0c949e7 commit 6db0a64

File tree

3 files changed

+59
-47
lines changed

3 files changed

+59
-47
lines changed

easybuild/framework/easyblock.py

Lines changed: 26 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1399,43 +1399,40 @@ def make_module_pythonpath(self):
13991399
Add lines for module file to update $PYTHONPATH or $EBPYTHONPREFIXES,
14001400
if they aren't already present and the standard lib/python*/site-packages subdirectory exists
14011401
"""
1402-
lines = []
1403-
if not os.path.isfile(os.path.join(self.installdir, 'bin', 'python')): # only needed when not a python install
1404-
python_subdir_pattern = os.path.join(self.installdir, 'lib', 'python*', 'site-packages')
1405-
candidate_paths = (os.path.relpath(path, self.installdir) for path in glob.glob(python_subdir_pattern))
1406-
python_paths = [path for path in candidate_paths if re.match(r'lib/python\d+\.\d+/site-packages', path)]
1402+
if os.path.isfile(os.path.join(self.installdir, 'bin', 'python')): # only needed when not a python install
1403+
return []
14071404

1408-
# determine whether Python is a runtime dependency;
1409-
# if so, we assume it was installed with EasyBuild, and hence is aware of $EBPYTHONPREFIXES
1410-
runtime_deps = [dep['name'] for dep in self.cfg.dependencies(runtime_only=True)]
1405+
python_subdir_pattern = os.path.join(self.installdir, 'lib', 'python*', 'site-packages')
1406+
candidate_paths = (os.path.relpath(path, self.installdir) for path in glob.glob(python_subdir_pattern))
1407+
python_paths = [path for path in candidate_paths if re.match(r'lib/python\d+\.\d+/site-packages', path)]
1408+
if not python_paths:
1409+
return []
14111410

1412-
# don't use $EBPYTHONPREFIXES unless we can and it's preferred or necesary (due to use of multi_deps)
1413-
use_ebpythonprefixes = False
1414-
multi_deps = self.cfg['multi_deps']
1411+
# determine whether Python is a runtime dependency;
1412+
# if so, we assume it was installed with EasyBuild, and hence is aware of $EBPYTHONPREFIXES
1413+
runtime_deps = [dep['name'] for dep in self.cfg.dependencies(runtime_only=True)]
14151414

1416-
if 'Python' in runtime_deps:
1417-
self.log.info("Found Python runtime dependency, so considering $EBPYTHONPREFIXES...")
1415+
# don't use $EBPYTHONPREFIXES unless we can and it's preferred or necesary (due to use of multi_deps)
1416+
use_ebpythonprefixes = False
1417+
multi_deps = self.cfg['multi_deps']
14181418

1419-
if build_option('prefer_python_search_path') == EBPYTHONPREFIXES:
1420-
self.log.info("Preferred Python search path is $EBPYTHONPREFIXES, so using that")
1421-
use_ebpythonprefixes = True
1419+
if 'Python' in runtime_deps:
1420+
self.log.info("Found Python runtime dependency, so considering $EBPYTHONPREFIXES...")
14221421

1423-
elif multi_deps and 'Python' in multi_deps:
1424-
self.log.info("Python is listed in 'multi_deps', so using $EBPYTHONPREFIXES instead of $PYTHONPATH")
1422+
if build_option('prefer_python_search_path') == EBPYTHONPREFIXES:
1423+
self.log.info("Preferred Python search path is $EBPYTHONPREFIXES, so using that")
14251424
use_ebpythonprefixes = True
14261425

1427-
if python_paths:
1428-
# add paths unless they were already added
1429-
if use_ebpythonprefixes:
1430-
path = '' # EBPYTHONPREFIXES are relative to the install dir
1431-
if path not in self.module_generator.added_paths_per_key[EBPYTHONPREFIXES]:
1432-
lines.append(self.module_generator.prepend_paths(EBPYTHONPREFIXES, path))
1433-
else:
1434-
for python_path in python_paths:
1435-
if python_path not in self.module_generator.added_paths_per_key[PYTHONPATH]:
1436-
lines.append(self.module_generator.prepend_paths(PYTHONPATH, python_path))
1426+
elif multi_deps and 'Python' in multi_deps:
1427+
self.log.info("Python is listed in 'multi_deps', so using $EBPYTHONPREFIXES instead of $PYTHONPATH")
1428+
use_ebpythonprefixes = True
14371429

1438-
return lines
1430+
if use_ebpythonprefixes:
1431+
path = '' # EBPYTHONPREFIXES are relative to the install dir
1432+
lines = self.module_generator.prepend_paths(EBPYTHONPREFIXES, path, warn_exists=False)
1433+
else:
1434+
lines = self.module_generator.prepend_paths(PYTHONPATH, python_paths, warn_exists=False)
1435+
return [lines] if lines else []
14391436

14401437
def make_module_extra(self, altroot=None, altversion=None):
14411438
"""

easybuild/tools/module_generator.py

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -206,8 +206,12 @@ def get_modules_path(self, fake=False, mod_path_suffix=None):
206206

207207
return os.path.join(mod_path, mod_path_suffix)
208208

209-
def _filter_paths(self, key, paths):
210-
"""Filter out paths already added to key and return the remaining ones"""
209+
def _filter_paths(self, key, paths, warn_exists=True):
210+
"""
211+
Filter out paths already added to key and return the remaining ones
212+
213+
:param warn_exists: Show a warning for paths already added to the key
214+
"""
211215
if self.added_paths_per_key is None:
212216
# For compatibility this is only a warning for now and we don't filter any paths
213217
print_warning('Module creation has not been started. Call start_module_creation first!')
@@ -227,15 +231,17 @@ def _filter_paths(self, key, paths):
227231
paths = list(paths)
228232
filtered_paths = [x for x in paths if x not in added_paths and not added_paths.add(x)]
229233
if filtered_paths != paths:
230-
removed_paths = paths if filtered_paths is None else [x for x in paths if x not in filtered_paths]
231-
print_warning("Suppressed adding the following path(s) to $%s of the module as they were already added: %s",
232-
key, removed_paths,
233-
log=self.log)
234+
if warn_exists:
235+
removed_paths = paths if filtered_paths is None else [x for x in paths if x not in filtered_paths]
236+
print_warning("Suppressed adding the following path(s) to $%s of the module "
237+
"as they were already added: %s",
238+
key, removed_paths,
239+
log=self.log)
234240
if not filtered_paths:
235241
filtered_paths = None
236242
return filtered_paths
237243

238-
def append_paths(self, key, paths, allow_abs=False, expand_relpaths=True, delim=':'):
244+
def append_paths(self, key, paths, allow_abs=False, expand_relpaths=True, delim=':', warn_exists=True):
239245
"""
240246
Generate append-path statements for the given list of paths.
241247
@@ -244,14 +250,15 @@ def append_paths(self, key, paths, allow_abs=False, expand_relpaths=True, delim=
244250
:param allow_abs: allow providing of absolute paths
245251
:param expand_relpaths: expand relative paths into absolute paths (by prefixing install dir)
246252
:param delim: delimiter used between paths
253+
:param warn_exists: Show a warning if any path was already added to the variable
247254
"""
248-
paths = self._filter_paths(key, paths)
255+
paths = self._filter_paths(key, paths, warn_exists=warn_exists)
249256
if paths is None:
250257
return ''
251258
return self.update_paths(key, paths, prepend=False, allow_abs=allow_abs, expand_relpaths=expand_relpaths,
252259
delim=delim)
253260

254-
def prepend_paths(self, key, paths, allow_abs=False, expand_relpaths=True, delim=':'):
261+
def prepend_paths(self, key, paths, allow_abs=False, expand_relpaths=True, delim=':', warn_exists=True):
255262
"""
256263
Generate prepend-path statements for the given list of paths.
257264
@@ -260,8 +267,9 @@ def prepend_paths(self, key, paths, allow_abs=False, expand_relpaths=True, delim
260267
:param allow_abs: allow providing of absolute paths
261268
:param expand_relpaths: expand relative paths into absolute paths (by prefixing install dir)
262269
:param delim: delimiter used between paths
270+
:param warn_exists: Show a warning if any path was already added to the variable
263271
"""
264-
paths = self._filter_paths(key, paths)
272+
paths = self._filter_paths(key, paths, warn_exists=warn_exists)
265273
if paths is None:
266274
return ''
267275
return self.update_paths(key, paths, prepend=True, allow_abs=allow_abs, expand_relpaths=expand_relpaths,

test/framework/module_generator.py

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -782,13 +782,16 @@ def append_paths(*args, **kwargs):
782782
# check for warning that is printed when same path is added multiple times
783783
with self.modgen.start_module_creation():
784784
self.modgen.append_paths('TEST', 'path1')
785-
self.mock_stderr(True)
786-
self.modgen.append_paths('TEST', 'path1')
787-
stderr = self.get_stderr()
788-
self.mock_stderr(False)
785+
with self.mocked_stdout_stderr():
786+
self.modgen.append_paths('TEST', 'path1')
787+
stderr = self.get_stderr()
789788
expected_warning = "\nWARNING: Suppressed adding the following path(s) to $TEST of the module "
790789
expected_warning += "as they were already added: path1\n\n"
791790
self.assertEqual(stderr, expected_warning)
791+
with self.mocked_stdout_stderr():
792+
self.modgen.append_paths('TEST', 'path1', warn_exists=False)
793+
stderr = self.get_stderr()
794+
self.assertEqual(stderr, '')
792795

793796
def test_module_extensions(self):
794797
"""test the extensions() for extensions"""
@@ -882,14 +885,18 @@ def prepend_paths(*args, **kwargs):
882885
# check for warning that is printed when same path is added multiple times
883886
with self.modgen.start_module_creation():
884887
self.modgen.prepend_paths('TEST', 'path1')
885-
self.mock_stderr(True)
886-
self.modgen.prepend_paths('TEST', 'path1')
887-
stderr = self.get_stderr()
888-
self.mock_stderr(False)
888+
with self.mocked_stdout_stderr():
889+
self.modgen.prepend_paths('TEST', 'path1')
890+
stderr = self.get_stderr()
889891
expected_warning = "\nWARNING: Suppressed adding the following path(s) to $TEST of the module "
890892
expected_warning += "as they were already added: path1\n\n"
891893
self.assertEqual(stderr, expected_warning)
892894

895+
with self.mocked_stdout_stderr():
896+
self.modgen.prepend_paths('TEST', 'path1', warn_exists=False)
897+
stderr = self.get_stderr()
898+
self.assertEqual(stderr, '')
899+
893900
def test_det_user_modpath(self):
894901
"""Test for generic det_user_modpath method."""
895902
# None by default

0 commit comments

Comments
 (0)