Skip to content
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

Print a warning when mixing $EBPYTHONPREFIXES and $PYTHONPATH modules #3521

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 37 additions & 2 deletions easybuild/easyblocks/generic/pythonpackage.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
from easybuild.framework.easyconfig.default import DEFAULT_CONFIG
from easybuild.framework.easyconfig.templates import TEMPLATE_CONSTANTS
from easybuild.framework.extensioneasyblock import ExtensionEasyBlock
from easybuild.tools.build_log import EasyBuildError, print_msg
from easybuild.tools.build_log import EasyBuildError, print_msg, print_warning
from easybuild.tools.config import build_option
from easybuild.tools.filetools import change_dir, mkdir, remove_dir, symlink, which
from easybuild.tools.modules import get_software_root
Expand Down Expand Up @@ -508,6 +508,41 @@ def set_pylibdirs(self):
self.all_pylibdirs = get_pylibdirs(python_cmd=self.python_cmd)
self.pylibdir = self.all_pylibdirs[0]

def verify_eb_pythonprefixes(self):
"""Warn if mixing dependency modules with $PYTHONPATH and $EBPYTHONPREFIXES"""
python_root = get_software_root('Python')
# Our site-customize is installed into the Python module. If that isn't loaded there is nothing to check.
if not python_root:
return
pythonpaths_var = os.environ.get('PYTHONPATH')
if not (os.environ.get(EBPYTHONPREFIXES) and pythonpaths_var):
self.log.debug('At most one of $PYTHONPATH and $%s is set. Skipping conflict check.', EBPYTHONPREFIXES)
return
# Check if any entry from $PYTHONPATH is from a dependent module.
# Resolve symlinks (only works for existing paths) to match the strings later.
pythonpaths = [os.path.realpath(path) for path in pythonpaths_var.split(os.path.pathsep)
if os.path.exists(path)]
# Check only paths that could be replaced by $EBPYTHONPREFIXES to avoid false positives
pythonpaths = [path for path in pythonpaths if path.endswith(os.sep + self.pylibdir)]
self.log.debug('Keeping %s from $PYTHONPATH=%s for checking', pythonpaths, pythonpaths_var)

def is_in_pythonpaths(dependency):
if dependency['name'] == 'Python':
return False # Ignore the Python module
try:
root = os.path.realpath(get_software_root(dependency['name']))
except OSError:
return False
# Search for the path or a subdirectory of it
return any(path == root or path.startswith(root + os.sep) for path in pythonpaths)

conflicts = [dep['name'] for dep in self.cfg.dependencies() if is_in_pythonpaths(dep)]
if conflicts:
print_warning('The following modules set $PYTHONPATH but $%s is also used: %s\n'
'Mixing such modules might cause unexpected results during the build of Python packages. '
'Try rebuilding the module files to use either $PYTHONPATH or $%s.',
EBPYTHONPREFIXES, ', '.join(conflicts), EBPYTHONPREFIXES)

def prepare_python(self):
"""Python-specific preparations."""

Expand Down Expand Up @@ -562,8 +597,8 @@ def prepare_python(self):
self.log.info("Python command being used: %s", self.python_cmd)

if self.python_cmd:
# set Python lib directories
self.set_pylibdirs()
self.verify_eb_pythonprefixes()

def _should_unpack_source(self):
"""Determine whether we need to unpack the source(s)"""
Expand Down