diff options
author | Daniele Nicolodi <daniele@grinta.net> | 2023-02-06 12:27:44 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-02-06 11:27:44 +0000 |
commit | 7ff4da6e8f835867e01e36166cef4fe8a2be8b4b (patch) | |
tree | f5794126cd0b75af999e81e7c6e371259dd0468a | |
parent | 9abb3c899a3b6e4dad590791f3c8d2421bce66c5 (diff) | |
download | pip-7ff4da6e8f835867e01e36166cef4fe8a2be8b4b.tar.gz |
Reconcile computation of isolated build environment paths (#11740)
Use the same code to determine isolated environment paths at
dependency install time and at environment setup time. We do not care
about the exact paths but the paths needs to be consistent at package
installation time and environment setup.
This should fix issues observed on platforms that customize the
installation schemes, such as Debian and Homebrew, where dependency
installation and isolated build environment setup resolved to
different paths.
-rw-r--r-- | news/11740.bugfix.rst | 3 | ||||
-rw-r--r-- | src/pip/_internal/build_env.py | 18 | ||||
-rw-r--r-- | src/pip/_internal/locations/__init__.py | 68 | ||||
-rw-r--r-- | src/pip/_internal/locations/_distutils.py | 9 | ||||
-rw-r--r-- | src/pip/_internal/locations/_sysconfig.py | 12 |
5 files changed, 14 insertions, 96 deletions
diff --git a/news/11740.bugfix.rst b/news/11740.bugfix.rst new file mode 100644 index 000000000..917beb535 --- /dev/null +++ b/news/11740.bugfix.rst @@ -0,0 +1,3 @@ +Improve handling of isolated build environments on platforms that +customize the Python's installation schemes, such as Debian and +Homebrew. diff --git a/src/pip/_internal/build_env.py b/src/pip/_internal/build_env.py index 24bfa870b..4f704a354 100644 --- a/src/pip/_internal/build_env.py +++ b/src/pip/_internal/build_env.py @@ -9,7 +9,7 @@ import sys import textwrap from collections import OrderedDict from types import TracebackType -from typing import TYPE_CHECKING, Iterable, List, Optional, Set, Tuple, Type +from typing import TYPE_CHECKING, Iterable, List, Optional, Set, Tuple, Type, Union from pip._vendor.certifi import where from pip._vendor.packaging.requirements import Requirement @@ -17,12 +17,7 @@ from pip._vendor.packaging.version import Version from pip import __file__ as pip_location from pip._internal.cli.spinners import open_spinner -from pip._internal.locations import ( - get_isolated_environment_bin_path, - get_isolated_environment_lib_paths, - get_platlib, - get_purelib, -) +from pip._internal.locations import get_platlib, get_purelib, get_scheme from pip._internal.metadata import get_default_environment, get_environment from pip._internal.utils.subprocess import call_subprocess from pip._internal.utils.temp_dir import TempDirectory, tempdir_kinds @@ -33,12 +28,17 @@ if TYPE_CHECKING: logger = logging.getLogger(__name__) +def _dedup(a: str, b: str) -> Union[Tuple[str], Tuple[str, str]]: + return (a, b) if a != b else (a,) + + class _Prefix: def __init__(self, path: str) -> None: self.path = path self.setup = False - self.bin_dir = get_isolated_environment_bin_path(path) - self.lib_dirs = get_isolated_environment_lib_paths(path) + scheme = get_scheme("", prefix=path) + self.bin_dir = scheme.scripts + self.lib_dirs = _dedup(scheme.purelib, scheme.platlib) def get_runnable_pip() -> str: diff --git a/src/pip/_internal/locations/__init__.py b/src/pip/_internal/locations/__init__.py index 496844be1..d54bc63eb 100644 --- a/src/pip/_internal/locations/__init__.py +++ b/src/pip/_internal/locations/__init__.py @@ -4,7 +4,7 @@ import os import pathlib import sys import sysconfig -from typing import Any, Dict, Generator, List, Optional, Tuple +from typing import Any, Dict, Generator, Optional, Tuple from pip._internal.models.scheme import SCHEME_KEYS, Scheme from pip._internal.utils.compat import WINDOWS @@ -25,8 +25,6 @@ __all__ = [ "USER_CACHE_DIR", "get_bin_prefix", "get_bin_user", - "get_isolated_environment_bin_path", - "get_isolated_environment_lib_paths", "get_major_minor_version", "get_platlib", "get_purelib", @@ -467,67 +465,3 @@ def get_platlib() -> str: if _warn_if_mismatch(pathlib.Path(old), pathlib.Path(new), key="platlib"): _log_context() return old - - -def _deduplicated(v1: str, v2: str) -> List[str]: - """Deduplicate values from a list.""" - if v1 == v2: - return [v1] - return [v1, v2] - - -def _looks_like_apple_library(path: str) -> bool: - """Apple patches sysconfig to *always* look under */Library/Python*.""" - if sys.platform[:6] != "darwin": - return False - return path == f"/Library/Python/{get_major_minor_version()}/site-packages" - - -def get_isolated_environment_lib_paths(prefix: str) -> List[str]: - """Return the lib locations under ``prefix``.""" - new_pure, new_plat = _sysconfig.get_isolated_environment_lib_paths(prefix) - if _USE_SYSCONFIG: - return _deduplicated(new_pure, new_plat) - - old_pure, old_plat = _distutils.get_isolated_environment_lib_paths(prefix) - old_lib_paths = _deduplicated(old_pure, old_plat) - - # Apple's Python (shipped with Xcode and Command Line Tools) hard-code - # platlib and purelib to '/Library/Python/X.Y/site-packages'. This will - # cause serious build isolation bugs when Apple starts shipping 3.10 because - # pip will install build backends to the wrong location. This tells users - # who is at fault so Apple may notice it and fix the issue in time. - if all(_looks_like_apple_library(p) for p in old_lib_paths): - deprecated( - reason=( - "Python distributed by Apple's Command Line Tools incorrectly " - "patches sysconfig to always point to '/Library/Python'. This " - "will cause build isolation to operate incorrectly on Python " - "3.10 or later. Please help report this to Apple so they can " - "fix this. https://developer.apple.com/bug-reporting/" - ), - replacement=None, - gone_in=None, - ) - return old_lib_paths - - warned = [ - _warn_if_mismatch( - pathlib.Path(old_pure), - pathlib.Path(new_pure), - key="prefixed-purelib", - ), - _warn_if_mismatch( - pathlib.Path(old_plat), - pathlib.Path(new_plat), - key="prefixed-platlib", - ), - ] - if any(warned): - _log_context(prefix=prefix) - - return old_lib_paths - - -def get_isolated_environment_bin_path(prefix: str) -> str: - return _sysconfig.get_isolated_environment_paths(prefix)["scripts"] diff --git a/src/pip/_internal/locations/_distutils.py b/src/pip/_internal/locations/_distutils.py index a6fbcd2f0..92bd93179 100644 --- a/src/pip/_internal/locations/_distutils.py +++ b/src/pip/_internal/locations/_distutils.py @@ -21,7 +21,7 @@ from distutils.cmd import Command as DistutilsCommand from distutils.command.install import SCHEME_KEYS from distutils.command.install import install as distutils_install_command from distutils.sysconfig import get_python_lib -from typing import Dict, List, Optional, Tuple, Union, cast +from typing import Dict, List, Optional, Union, cast from pip._internal.models.scheme import Scheme from pip._internal.utils.compat import WINDOWS @@ -171,10 +171,3 @@ def get_purelib() -> str: def get_platlib() -> str: return get_python_lib(plat_specific=True) - - -def get_isolated_environment_lib_paths(prefix: str) -> Tuple[str, str]: - return ( - get_python_lib(plat_specific=False, prefix=prefix), - get_python_lib(plat_specific=True, prefix=prefix), - ) diff --git a/src/pip/_internal/locations/_sysconfig.py b/src/pip/_internal/locations/_sysconfig.py index 38e400f94..97aef1f1a 100644 --- a/src/pip/_internal/locations/_sysconfig.py +++ b/src/pip/_internal/locations/_sysconfig.py @@ -211,15 +211,3 @@ def get_purelib() -> str: def get_platlib() -> str: return sysconfig.get_paths()["platlib"] - - -def get_isolated_environment_paths(prefix: str) -> typing.Dict[str, str]: - variables = {"base": prefix, "platbase": prefix} - if "venv" in sysconfig.get_scheme_names(): - return sysconfig.get_paths(vars=variables, scheme="venv") - return sysconfig.get_paths(vars=variables) - - -def get_isolated_environment_lib_paths(prefix: str) -> typing.Tuple[str, str]: - paths = get_isolated_environment_paths(prefix) - return (paths["purelib"], paths["platlib"]) |