2828@author: Kenneth Hoste (Ghent University)
2929"""
3030import os
31- import sys
3231
3332from easybuild .easyblocks .generic .bundle import Bundle
3433from easybuild .easyblocks .generic .pythonpackage import EBPYTHONPREFIXES , EXTS_FILTER_PYTHON_PACKAGES
35- from easybuild .easyblocks .generic .pythonpackage import PythonPackage , get_pylibdirs , pick_python_cmd
34+ from easybuild .easyblocks .generic .pythonpackage import PythonPackage , get_pylibdirs , find_python_cmd , run_pip_check
3635from easybuild .tools .build_log import EasyBuildError
37- from easybuild .tools .filetools import which
3836from easybuild .tools .modules import get_software_root
3937import easybuild .tools .environment as env
4038
@@ -74,49 +72,33 @@ def __init__(self, *args, **kwargs):
7472
7573 self .log .info ("exts_default_options: %s" , self .cfg ['exts_default_options' ])
7674
75+ self .python_cmd = None
7776 self .pylibdir = None
78- self .all_pylibdirs = []
77+ self .all_pylibdirs = None
7978
8079 # figure out whether this bundle of Python packages is being installed for multiple Python versions
8180 self .multi_python = 'Python' in self .cfg ['multi_deps' ]
8281
83- def prepare_step (self , * args , ** kwargs ):
84- """Prepare for installing bundle of Python packages."""
85- super (Bundle , self ).prepare_step (* args , ** kwargs )
82+ def prepare_python (self ):
83+ """Python-specific preparations."""
8684
87- python_root = get_software_root ('Python' )
88- if python_root is None :
85+ if get_software_root ('Python' ) is None :
8986 raise EasyBuildError ("Python not included as dependency!" )
87+ self .python_cmd = find_python_cmd (self .log , self .cfg ['req_py_majver' ], self .cfg ['req_py_minver' ], required = True )
9088
91- # when system Python is used, the first 'python' command in $PATH will not be $EBROOTPYTHON/bin/python,
92- # since $EBROOTPYTHON is set to just 'Python' in that case
93- # (see handling of allow_system_deps in EasyBlock.prepare_step)
94- if which ('python' ) == os .path .join (python_root , 'bin' , 'python' ):
95- # if we're using a proper Python dependency, let det_pylibdir use 'python' like it does by default
96- python_cmd = None
97- else :
98- # since det_pylibdir will use 'python' by default as command to determine Python lib directory,
99- # we need to intervene when the system Python is used, by specifying version requirements
100- # to pick_python_cmd so the right 'python' command is used;
101- # if we're using the system Python and no Python version requirements are specified,
102- # use major/minor version of Python being used in this EasyBuild session (as we also do in PythonPackage)
103- req_py_majver = self .cfg ['req_py_majver' ]
104- if req_py_majver is None :
105- req_py_majver = sys .version_info [0 ]
106- req_py_minver = self .cfg ['req_py_minver' ]
107- if req_py_minver is None :
108- req_py_minver = sys .version_info [1 ]
109-
110- python_cmd = pick_python_cmd (req_maj_ver = req_py_majver , req_min_ver = req_py_minver )
111-
112- self .all_pylibdirs = get_pylibdirs (python_cmd = python_cmd )
89+ self .all_pylibdirs = get_pylibdirs (python_cmd = self .python_cmd )
11390 self .pylibdir = self .all_pylibdirs [0 ]
11491
11592 # if 'python' is not used, we need to take that into account in the extensions filter
11693 # (which is also used during the sanity check)
117- if python_cmd :
94+ if self . python_cmd != 'python' :
11895 orig_exts_filter = EXTS_FILTER_PYTHON_PACKAGES
119- self .cfg ['exts_filter' ] = (orig_exts_filter [0 ].replace ('python' , python_cmd ), orig_exts_filter [1 ])
96+ self .cfg ['exts_filter' ] = (orig_exts_filter [0 ].replace ('python' , self .python_cmd ), orig_exts_filter [1 ])
97+
98+ def prepare_step (self , * args , ** kwargs ):
99+ """Prepare for installing bundle of Python packages."""
100+ super (Bundle , self ).prepare_step (* args , ** kwargs )
101+ self .prepare_python ()
120102
121103 def extensions_step (self , * args , ** kwargs ):
122104 """Install extensions (usually PythonPackages)"""
@@ -158,6 +140,13 @@ def make_module_extra(self, *args, **kwargs):
158140 def sanity_check_step (self , * args , ** kwargs ):
159141 """Custom sanity check for bundle of Python package."""
160142
143+ if self .pylibdir is None :
144+ # Python attributes not set up yet, happens e.g. with --sanity-check-only
145+ # Load module first to get the right python command
146+ self .fake_mod_data = self .sanity_check_load_module (extension = kwargs .get ('extension' , False ),
147+ extra_modules = kwargs .get ('extra_modules' , None ))
148+ self .prepare_python ()
149+
161150 # inject directory path that uses %(pyshortver)s template into default value for sanity_check_paths
162151 # this is relevant for installations of Python bundles for multiple Python versions (via multi_deps)
163152 # (we can not pass this via custom_paths, since then the %(pyshortver)s template value will not be resolved)
@@ -168,3 +157,24 @@ def sanity_check_step(self, *args, **kwargs):
168157 }
169158
170159 super (Bundle , self ).sanity_check_step (* args , ** kwargs )
160+
161+ # After the super-call self.ext_instances is initialized, so we can check the extensions
162+ sanity_pip_check = self .cfg ['sanity_pip_check' ]
163+ unversioned_packages = set (self .cfg ['unversioned_packages' ])
164+ has_sanity_pip_check_mismatch = False
165+ all_unversioned_packages = unversioned_packages .copy ()
166+ for ext in self .ext_instances :
167+ if isinstance (ext , PythonPackage ):
168+ if ext .cfg ['sanity_pip_check' ] != sanity_pip_check :
169+ has_sanity_pip_check_mismatch = True
170+ all_unversioned_packages .update (ext .cfg ['unversioned_packages' ])
171+
172+ if has_sanity_pip_check_mismatch :
173+ self .log .deprecated ('For bundles of PythonPackage the sanity_pip_check option '
174+ 'in the main EasyConfig must be used' , '5.0' )
175+ sanity_pip_check = True # Either the main set it or any extension enabled it
176+ if all_unversioned_packages != unversioned_packages :
177+ self .log .deprecated ('For bundles of PythonPackage the unversioned_packages option '
178+ 'in the main EasyConfig must be used' , '5.0' )
179+ if sanity_pip_check :
180+ run_pip_check (self .log , self .python_cmd , all_unversioned_packages )
0 commit comments