-
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
Prefer $EBPYTHONPREFIXES
over $PYTHONPATH
#4496
Changes from 9 commits
0ec2df5
74a3cb3
03e304e
b07ea3f
8c66e1a
ccd3d7e
f76f320
8b5389f
cb6adb0
4a11f2f
c471e03
2676e4e
f4fbe76
92f0e62
e91186e
236c67f
ca304fb
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 | ||||
---|---|---|---|---|---|---|
|
@@ -213,22 +213,14 @@ def _filter_paths(self, key, paths): | |||||
return paths | ||||||
|
||||||
added_paths = self.added_paths_per_key.setdefault(key, set()) | ||||||
# paths can be a string | ||||||
if isinstance(paths, str): | ||||||
if paths in added_paths: | ||||||
filtered_paths = None | ||||||
else: | ||||||
added_paths.add(paths) | ||||||
filtered_paths = paths | ||||||
else: | ||||||
# Coerce any iterable/generator into a list | ||||||
if not isinstance(paths, list): | ||||||
paths = list(paths) | ||||||
filtered_paths = [x for x in paths if x not in added_paths and not added_paths.add(x)] | ||||||
# Coerce any iterable/generator into a list | ||||||
if not isinstance(paths, list): | ||||||
paths = list(paths) | ||||||
filtered_paths = [x for x in paths if x not in added_paths and not added_paths.add(x)] | ||||||
if filtered_paths != paths: | ||||||
removed_paths = paths if filtered_paths is None else [x for x in paths if x not in filtered_paths] | ||||||
print_warning("Suppressed adding the following path(s) to $%s of the module as they were already added: %s", | ||||||
Micket marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
key, removed_paths, | ||||||
key, ', '.join(removed_paths), | ||||||
log=self.log) | ||||||
if not filtered_paths: | ||||||
filtered_paths = None | ||||||
|
@@ -243,9 +235,6 @@ def append_paths(self, key, paths, allow_abs=False, expand_relpaths=True): | |||||
:param allow_abs: allow providing of absolute paths | ||||||
:param expand_relpaths: expand relative paths into absolute paths (by prefixing install dir) | ||||||
""" | ||||||
paths = self._filter_paths(key, paths) | ||||||
if paths is None: | ||||||
return '' | ||||||
return self.update_paths(key, paths, prepend=False, allow_abs=allow_abs, expand_relpaths=expand_relpaths) | ||||||
|
||||||
def prepend_paths(self, key, paths, allow_abs=False, expand_relpaths=True): | ||||||
|
@@ -257,11 +246,38 @@ def prepend_paths(self, key, paths, allow_abs=False, expand_relpaths=True): | |||||
:param allow_abs: allow providing of absolute paths | ||||||
:param expand_relpaths: expand relative paths into absolute paths (by prefixing install dir) | ||||||
""" | ||||||
paths = self._filter_paths(key, paths) | ||||||
if paths is None: | ||||||
return '' | ||||||
return self.update_paths(key, paths, prepend=True, allow_abs=allow_abs, expand_relpaths=expand_relpaths) | ||||||
|
||||||
def update_paths(self, key, paths, prepend=True, allow_abs=False, expand_relpaths=True): | ||||||
""" | ||||||
Generate append/prepend-path statements for the given list of paths. | ||||||
|
||||||
:param key: environment variable to append paths to | ||||||
:param paths: list of paths to append | ||||||
:param allow_abs: allow providing of absolute paths | ||||||
:param expand_relpaths: expand relative paths into absolute paths (by prefixing install dir) | ||||||
""" | ||||||
if isinstance(paths, str): | ||||||
self.log.debug("Wrapping %s into a list before using it for %s", paths, key) | ||||||
paths = [paths] | ||||||
|
||||||
if key == 'PYTHONPATH': | ||||||
python_paths = [path for path in paths if re.match(r'lib/python\d+\.\d+/site-packages', path)] | ||||||
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. Checking the logic in This means it this point Similar to my previous reasoning about breaking change in favor of cleaner code: I would simply disallow passing anything but a a string or a list to Quick example:
Micket marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
if len(python_paths) > 1: | ||||||
raise EasyBuildError('Found multiple paths for PYTHONPATH: ' + ', '.join(python_paths)) | ||||||
|
||||||
# Special condition for PYTHONPATHs that match the standard pattern, | ||||||
# replace with EBPYTHONPREFIX which is added to python sys path at runtime | ||||||
if python_paths and build_option('prefer_ebpythonprefix_over_pythonpath'): | ||||||
python_path = python_paths[0] | ||||||
self.log.info("Replaced PYTHONPATH %s with EBPYTHONPREFIXES", python_path) | ||||||
ret = self._update_paths('EBPYTHONPREFIXES', [''], prepend, allow_abs, expand_relpaths) | ||||||
paths = [path for path in paths if path != python_path] | ||||||
if paths: | ||||||
ret += self._update_paths(key, paths, prepend, allow_abs, expand_relpaths) | ||||||
return ret | ||||||
return self._update_paths(key, paths, prepend, allow_abs, expand_relpaths) | ||||||
|
||||||
def _modulerc_check_module_version(self, module_version): | ||||||
""" | ||||||
Check value type & contents of specified module-version spec. | ||||||
|
@@ -551,7 +567,7 @@ def unload_module(self, mod_name): | |||||
""" | ||||||
raise NotImplementedError | ||||||
|
||||||
def update_paths(self, key, paths, prepend=True, allow_abs=False, expand_relpaths=True): | ||||||
def _update_paths(self, key, paths, prepend=True, allow_abs=False, expand_relpaths=True): | ||||||
""" | ||||||
Generate prepend-path or append-path statements for the given list of paths. | ||||||
|
||||||
|
@@ -955,7 +971,7 @@ def msg_on_unload(self, msg): | |||||
print_cmd = "puts stderr %s" % quote_str(msg, tcl=True) | ||||||
return '\n'.join(['', self.conditional_statement("module-info mode unload", print_cmd, indent=False)]) | ||||||
|
||||||
def update_paths(self, key, paths, prepend=True, allow_abs=False, expand_relpaths=True): | ||||||
def _update_paths(self, key, paths, prepend=True, allow_abs=False, expand_relpaths=True): | ||||||
""" | ||||||
Generate prepend-path or append-path statements for the given list of paths. | ||||||
|
||||||
|
@@ -965,6 +981,10 @@ def update_paths(self, key, paths, prepend=True, allow_abs=False, expand_relpath | |||||
:param allow_abs: allow providing of absolute paths | ||||||
:param expand_relpaths: expand relative paths into absolute paths (by prefixing install dir) | ||||||
""" | ||||||
paths = self._filter_paths(key, paths) | ||||||
if paths is None: | ||||||
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 was wondering about how the filtered paths could be
I would remove both checks, neither is required and we are actually checking stuff twice. Having If we really want to exit early here, then it is better to remove the above check in
Suggested change
That would at least check only once |
||||||
return '' | ||||||
|
||||||
if prepend: | ||||||
update_type = 'prepend' | ||||||
else: | ||||||
|
@@ -974,10 +994,6 @@ def update_paths(self, key, paths, prepend=True, allow_abs=False, expand_relpath | |||||
self.log.info("Not including statement to %s environment variable $%s, as specified", update_type, key) | ||||||
return '' | ||||||
|
||||||
if isinstance(paths, str): | ||||||
self.log.debug("Wrapping %s into a list before using it to %s path %s", paths, update_type, key) | ||||||
paths = [paths] | ||||||
|
||||||
abspaths = [] | ||||||
for path in paths: | ||||||
if os.path.isabs(path) and not allow_abs: | ||||||
|
@@ -1426,7 +1442,7 @@ def modulerc(self, module_version=None, filepath=None, modulerc_txt=None): | |||||
return super(ModuleGeneratorLua, self).modulerc(module_version=module_version, filepath=filepath, | ||||||
modulerc_txt=modulerc_txt) | ||||||
|
||||||
def update_paths(self, key, paths, prepend=True, allow_abs=False, expand_relpaths=True): | ||||||
def _update_paths(self, key, paths, prepend=True, allow_abs=False, expand_relpaths=True): | ||||||
""" | ||||||
Generate prepend_path or append_path statements for the given list of paths | ||||||
|
||||||
|
@@ -1436,6 +1452,10 @@ def update_paths(self, key, paths, prepend=True, allow_abs=False, expand_relpath | |||||
:param allow_abs: allow providing of absolute paths | ||||||
:param expand_relpaths: expand relative paths into absolute paths (by prefixing install dir) | ||||||
""" | ||||||
paths = self._filter_paths(key, paths) | ||||||
if paths is None: | ||||||
return '' | ||||||
|
||||||
if prepend: | ||||||
update_type = 'prepend' | ||||||
else: | ||||||
|
@@ -1445,10 +1465,6 @@ def update_paths(self, key, paths, prepend=True, allow_abs=False, expand_relpath | |||||
self.log.info("Not including statement to %s environment variable $%s, as specified", update_type, key) | ||||||
return '' | ||||||
|
||||||
if isinstance(paths, str): | ||||||
self.log.debug("Wrapping %s into a list before using it to %s path %s", update_type, paths, key) | ||||||
paths = [paths] | ||||||
|
||||||
abspaths = [] | ||||||
for path in paths: | ||||||
if os.path.isabs(path): | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -480,6 +480,8 @@ def override_options(self): | |
'int', 'store', None), | ||
'parallel-extensions-install': ("Install list of extensions in parallel (if supported)", | ||
None, 'store_true', False), | ||
'prefer-ebpythonprefix-over-pythonpath': ("Replaces PYTHONPATH with EBPYTHONPREFIX when possible", | ||
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. We bounced around a bunch of different names, so i'm currently thinking maybe The fact that it doesn't always replace pythonpath, exceptions really are very rare, and this wouldn't be the first option that does what is claims only when it is supported. |
||
None, 'store_true', True), | ||
'pre-create-installdir': ("Create installation directory before submitting build jobs", | ||
None, 'store_true', True), | ||
'pretend': (("Does the build/installation in a test directory located in $HOME/easybuildinstall"), | ||
|
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.
I'm a bit worried about the change here. Why changing
_filter_paths
and even removing the ability to pass a string (which is a breaking change leading to surprising behavior)?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.
The rest of the code (_update_paths) both converted the str case to a list. I simply moved this earlier, which also removes the need for _filter_paths to keep duplicate logic, since regardless it was always converted to a list immediately afterwards anyway.
You can pass a str to
paths
toappend/prepend/update_paths
.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.
Yes I see that our usages in this file basically make this part dead code. However someone or something else might already use this code, so I'm not sure if we should be a bit more careful here. E.g. at least error out when a string is passed instead of an iterable of strings
On the other hand: Calling this method from outside would have been wrong (it is "private") and this PR is targetting 5.x so a breaking change for simpler logic is fine.