|
49 | 49 | from easybuild.framework.extensioneasyblock import ExtensionEasyBlock |
50 | 50 | from easybuild.tools.build_log import EasyBuildError, print_msg |
51 | 51 | from easybuild.tools.config import build_option, PYTHONPATH, EBPYTHONPREFIXES |
52 | | -from easybuild.tools.filetools import change_dir, mkdir, read_file, remove_dir, symlink, which, write_file |
| 52 | +from easybuild.tools.filetools import change_dir, mkdir, read_file, remove_dir, symlink, which, write_file, search_file |
53 | 53 | from easybuild.tools.modules import ModEnvVarType, get_software_root |
54 | 54 | from easybuild.tools.run import run_shell_cmd |
55 | 55 | from easybuild.tools.utilities import nub |
@@ -618,6 +618,46 @@ def using_local_py_install_scheme(self): |
618 | 618 | py_install_scheme = det_py_install_scheme(python_cmd=self.python_cmd) |
619 | 619 | return py_install_scheme == PY_INSTALL_SCHEME_POSIX_LOCAL and self.using_pip_install() |
620 | 620 |
|
| 621 | + def should_use_ebpythonprefixes(self) -> bool: |
| 622 | + """ |
| 623 | + Determine if we should update $EBPYTHONPREFIXES rather than $PYTHONPATH. |
| 624 | + If this Python package was installed for multiple Python versions, the package is using |
| 625 | + .pth files, or if we prefer it; note: although EasyBuild framework also has logic for |
| 626 | + this in EasyBlock.make_module_extra, we retain full control here, since the logic is |
| 627 | + slightly different. |
| 628 | + """ |
| 629 | + |
| 630 | + use_ebpythonprefixes = False |
| 631 | + runtime_deps = [dep['name'] for dep in self.cfg.dependencies(runtime_only=True)] |
| 632 | + |
| 633 | + if 'Python' in runtime_deps: |
| 634 | + self.log.info("Found Python runtime dependency, so considering $EBPYTHONPREFIXES...") |
| 635 | + if build_option('prefer_python_search_path') == EBPYTHONPREFIXES: |
| 636 | + self.log.info("Preferred Python search path is $EBPYTHONPREFIXES, so using that") |
| 637 | + use_ebpythonprefixes = True |
| 638 | + |
| 639 | + # Check if the installdir or sources contain any .pth files. For them to work correctly, |
| 640 | + # Python needs these files to be in the sitedir path. While this typically works system-wide |
| 641 | + # or in a venv, having Python modules in separate directories is unusual, and only having |
| 642 | + # $PYTHONPATH will ignore these files. |
| 643 | + # Our sitecustomize.py adds paths in $EBPYTHONPREFIXES to the sitedir path though, allowing |
| 644 | + # these .pth files to work as expected. See: https://docs.python.org/3/library/site.html#module-site |
| 645 | + # .pth files always should be in the site folder, so most of the path is fixed. |
| 646 | + # Try the installation directory first |
| 647 | + if self.installdir and search_file([self.installdir], r".*\.pth$", silent=True): |
| 648 | + self.log.info(f"Found path configuration file in installation directory '{self.installdir}'. " |
| 649 | + "Enabling $EBPYTHONPREFIXES...") |
| 650 | + use_ebpythonprefixes = True |
| 651 | + # If we did a test installation, check that one as well. Ensure that pypkg_test_installdir is set, |
| 652 | + # since that might not be the case for sanity_check_only or module_only. |
| 653 | + if self.testinstall and self.pypkg_test_installdir: |
| 654 | + if search_file([self.pypkg_test_installdir], r".*\.pth$", silent=True): |
| 655 | + self.log.info("Found path configuration file in test installation directory " |
| 656 | + f"'{self.pypkg_test_installdir}'. Enabling $EBPYTHONPREFIXES...") |
| 657 | + use_ebpythonprefixes = True |
| 658 | + |
| 659 | + return self.multi_python or use_ebpythonprefixes |
| 660 | + |
621 | 661 | def compose_install_command(self, prefix, extrapath=None, installopts=None): |
622 | 662 | """Compose full install command.""" |
623 | 663 |
|
@@ -824,7 +864,7 @@ def test_step(self, return_output_ec=False): |
824 | 864 | out, ec = (None, None) |
825 | 865 |
|
826 | 866 | if self.testinstall: |
827 | | - # install in test directory and export PYTHONPATH |
| 867 | + # install in test directory and export PYTHONPATH and / or EBPYTHONPREFIX if we need it |
828 | 868 |
|
829 | 869 | try: |
830 | 870 | if self.pypkg_test_installdir is None: |
@@ -852,7 +892,9 @@ def test_step(self, return_output_ec=False): |
852 | 892 | # add install location to both $PYTHONPATH and $PATH |
853 | 893 | abs_pylibdirs = [os.path.join(actual_installdir, pylibdir) for pylibdir in self.all_pylibdirs] |
854 | 894 | extrapath = "export PYTHONPATH=%s && " % os.pathsep.join(abs_pylibdirs + ['$PYTHONPATH']) |
855 | | - |
| 895 | + if self.should_use_ebpythonprefixes(): |
| 896 | + extrapath += "export EBPYTHONPREFIXES=%s && " % os.pathsep.join([self.pypkg_test_installdir] + |
| 897 | + ['$EBPYTHONPREFIXES']) |
856 | 898 | extrapath += "export PATH=%s:$PATH && " % os.path.join(actual_installdir, 'bin') |
857 | 899 |
|
858 | 900 | cmd = self.compose_install_command(self.pypkg_test_installdir, extrapath=extrapath) |
@@ -1087,20 +1129,7 @@ def make_module_extra(self, *args, **kwargs): |
1087 | 1129 | """Add install path to PYTHONPATH""" |
1088 | 1130 | txt = '' |
1089 | 1131 |
|
1090 | | - # update $EBPYTHONPREFIXES rather than $PYTHONPATH |
1091 | | - # if this Python package was installed for multiple Python versions, or if we prefer it; |
1092 | | - # note: although EasyBuild framework also has logic for this in EasyBlock.make_module_extra, |
1093 | | - # we retain full control here, since the logic is slightly different |
1094 | | - use_ebpythonprefixes = False |
1095 | | - runtime_deps = [dep['name'] for dep in self.cfg.dependencies(runtime_only=True)] |
1096 | | - |
1097 | | - if 'Python' in runtime_deps: |
1098 | | - self.log.info("Found Python runtime dependency, so considering $EBPYTHONPREFIXES...") |
1099 | | - if build_option('prefer_python_search_path') == EBPYTHONPREFIXES: |
1100 | | - self.log.info("Preferred Python search path is $EBPYTHONPREFIXES, so using that") |
1101 | | - use_ebpythonprefixes = True |
1102 | | - |
1103 | | - if self.multi_python or use_ebpythonprefixes: |
| 1132 | + if self.should_use_ebpythonprefixes(): |
1104 | 1133 | path = '' # EBPYTHONPREFIXES are relative to the install dir |
1105 | 1134 | txt += self.module_generator.prepend_paths(EBPYTHONPREFIXES, path) |
1106 | 1135 | elif self.require_python: |
|
0 commit comments