|
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, \ |
| 53 | + find_glob_pattern |
53 | 54 | from easybuild.tools.modules import ModEnvVarType, get_software_root |
54 | 55 | from easybuild.tools.run import run_shell_cmd |
55 | 56 | from easybuild.tools.utilities import nub |
@@ -617,6 +618,54 @@ def using_local_py_install_scheme(self): |
617 | 618 | py_install_scheme = det_py_install_scheme(python_cmd=self.python_cmd) |
618 | 619 | return py_install_scheme == PY_INSTALL_SCHEME_POSIX_LOCAL and self.using_pip_install() |
619 | 620 |
|
| 621 | + def using_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: |
| 647 | + glob_pattern = "%s/lib/python*/site-packages/*.pth" |
| 648 | + # Try the installation directory first |
| 649 | + if find_glob_pattern(glob_pattern % self.installdir, |
| 650 | + fail_on_no_match=False): |
| 651 | + self.log.info("Found path configuration file in installation directory." |
| 652 | + "Enabling $EBPYTHONPREFIXES...") |
| 653 | + use_ebpythonprefixes = True |
| 654 | + # If we did a test installation, check that one as well |
| 655 | + if self.testinstall and find_glob_pattern(glob_pattern % self.pypkg_test_installdir, |
| 656 | + fail_on_no_match=False): |
| 657 | + self.log.info("Found path configuration file in test installation directory." |
| 658 | + "Enabling $EBPYTHONPREFIXES...") |
| 659 | + use_ebpythonprefixes = True |
| 660 | + except EasyBuildError: |
| 661 | + # find_glob_pattern found more than one match. This is still sufficient for us to assume |
| 662 | + # that we need $EBPYTHONPREFIXES. |
| 663 | + self.log.info("Found more than one match while searchin for path configuration files." |
| 664 | + "Enabling $EBPYTHONPREFIXES...") |
| 665 | + use_ebpythonprefixes = True |
| 666 | + |
| 667 | + return self.multi_python or use_ebpythonprefixes |
| 668 | + |
620 | 669 | def compose_install_command(self, prefix, extrapath=None, installopts=None): |
621 | 670 | """Compose full install command.""" |
622 | 671 |
|
@@ -821,7 +870,7 @@ def test_step(self, return_output_ec=False): |
821 | 870 | out, ec = (None, None) |
822 | 871 |
|
823 | 872 | if self.testinstall: |
824 | | - # install in test directory and export PYTHONPATH |
| 873 | + # install in test directory and export PYTHONPATH and / or EBPYTHONPREFIX if we need it |
825 | 874 |
|
826 | 875 | try: |
827 | 876 | if self.pypkg_test_installdir is None: |
@@ -849,7 +898,9 @@ def test_step(self, return_output_ec=False): |
849 | 898 | # add install location to both $PYTHONPATH and $PATH |
850 | 899 | abs_pylibdirs = [os.path.join(actual_installdir, pylibdir) for pylibdir in self.all_pylibdirs] |
851 | 900 | extrapath = "export PYTHONPATH=%s && " % os.pathsep.join(abs_pylibdirs + ['$PYTHONPATH']) |
852 | | - |
| 901 | + if self.using_ebpythonprefixes(): |
| 902 | + extrapath += "export EBPYTHONPREFIXES=%s && " % os.pathsep.join(abs_pylibdirs + |
| 903 | + ['$EBPYTHONPREFIXES']) |
853 | 904 | extrapath += "export PATH=%s:$PATH && " % os.path.join(actual_installdir, 'bin') |
854 | 905 |
|
855 | 906 | cmd = self.compose_install_command(self.pypkg_test_installdir, extrapath=extrapath) |
@@ -1084,20 +1135,7 @@ def make_module_extra(self, *args, **kwargs): |
1084 | 1135 | """Add install path to PYTHONPATH""" |
1085 | 1136 | txt = '' |
1086 | 1137 |
|
1087 | | - # update $EBPYTHONPREFIXES rather than $PYTHONPATH |
1088 | | - # if this Python package was installed for multiple Python versions, or if we prefer it; |
1089 | | - # note: although EasyBuild framework also has logic for this in EasyBlock.make_module_extra, |
1090 | | - # we retain full control here, since the logic is slightly different |
1091 | | - use_ebpythonprefixes = False |
1092 | | - runtime_deps = [dep['name'] for dep in self.cfg.dependencies(runtime_only=True)] |
1093 | | - |
1094 | | - if 'Python' in runtime_deps: |
1095 | | - self.log.info("Found Python runtime dependency, so considering $EBPYTHONPREFIXES...") |
1096 | | - if build_option('prefer_python_search_path') == EBPYTHONPREFIXES: |
1097 | | - self.log.info("Preferred Python search path is $EBPYTHONPREFIXES, so using that") |
1098 | | - use_ebpythonprefixes = True |
1099 | | - |
1100 | | - if self.multi_python or use_ebpythonprefixes: |
| 1138 | + if self.using_ebpythonprefixes(): |
1101 | 1139 | path = '' # EBPYTHONPREFIXES are relative to the install dir |
1102 | 1140 | txt += self.module_generator.prepend_paths(EBPYTHONPREFIXES, path) |
1103 | 1141 | elif self.require_python: |
|
0 commit comments