From 19e802250e93ee5c9b35ef72a70d0ae4e32155c4 Mon Sep 17 00:00:00 2001 From: Daniele Nicolodi Date: Tue, 15 Nov 2022 09:46:55 +0100 Subject: [PATCH 1/2] Use the "venv" scheme if available to obtain prefixed lib paths get_prefixed_libs() computes the Python path for libraries in a pip isolation environment. Python 3.11 introduced the "venv" path scheme to be used in these cases. Use it if available. This solves a bug on Homebrew's Python 3.10 and later where the default paths scheme when Python is invoked outside a virtual environment is "osx_framework_library" and does not relative to the "{base}" or "{platbase}" variables. Fixes #11539. --- news/11598.bugfix.rst | 1 + src/pip/_internal/locations/_sysconfig.py | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 news/11598.bugfix.rst diff --git a/news/11598.bugfix.rst b/news/11598.bugfix.rst new file mode 100644 index 00000000000..031ff9ddca0 --- /dev/null +++ b/news/11598.bugfix.rst @@ -0,0 +1 @@ +Use the "venv" scheme if available to obtain prefixed lib paths. diff --git a/src/pip/_internal/locations/_sysconfig.py b/src/pip/_internal/locations/_sysconfig.py index 0bbc9283db7..5c870c783b3 100644 --- a/src/pip/_internal/locations/_sysconfig.py +++ b/src/pip/_internal/locations/_sysconfig.py @@ -214,5 +214,9 @@ def get_platlib() -> str: def get_prefixed_libs(prefix: str) -> typing.Tuple[str, str]: - paths = sysconfig.get_paths(vars={"base": prefix, "platbase": prefix}) + vars = {"base": prefix, "platbase": prefix} + if "venv" in sysconfig.get_scheme_names(): + paths = sysconfig.get_paths(vars=vars, scheme="venv") + else: + paths = sysconfig.get_paths(vars=vars) return (paths["purelib"], paths["platlib"]) From f8beb61f1c7022c667936cd8e6998ec987f38daf Mon Sep 17 00:00:00 2001 From: Daniele Nicolodi Date: Wed, 16 Nov 2022 22:38:02 +0100 Subject: [PATCH 2/2] Rename get_prefixed_libs() to get_isolated_environment_lib_paths() Since this function is only used for creating isolated environments, rename it to better describe what it does. This avoids needing to think about why the implementation uses the "venv" paths scheme even when pip is not running in a virtual environment. --- src/pip/_internal/build_env.py | 8 ++++++-- src/pip/_internal/locations/__init__.py | 8 ++++---- src/pip/_internal/locations/_distutils.py | 2 +- src/pip/_internal/locations/_sysconfig.py | 2 +- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/pip/_internal/build_env.py b/src/pip/_internal/build_env.py index cc2b38bab79..e67b868e8f4 100644 --- a/src/pip/_internal/build_env.py +++ b/src/pip/_internal/build_env.py @@ -18,7 +18,11 @@ from pip import __file__ as pip_location from pip._internal.cli.spinners import open_spinner -from pip._internal.locations import get_platlib, get_prefixed_libs, get_purelib +from pip._internal.locations import ( + get_isolated_environment_lib_paths, + get_platlib, + get_purelib, +) 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 @@ -37,7 +41,7 @@ def __init__(self, path: str) -> None: "nt" if os.name == "nt" else "posix_prefix", vars={"base": path, "platbase": path}, )["scripts"] - self.lib_dirs = get_prefixed_libs(path) + self.lib_dirs = get_isolated_environment_lib_paths(path) def get_runnable_pip() -> str: diff --git a/src/pip/_internal/locations/__init__.py b/src/pip/_internal/locations/__init__.py index 60afe0a73b8..516bd607839 100644 --- a/src/pip/_internal/locations/__init__.py +++ b/src/pip/_internal/locations/__init__.py @@ -27,7 +27,7 @@ "get_bin_user", "get_major_minor_version", "get_platlib", - "get_prefixed_libs", + "get_isolated_environment_lib_paths", "get_purelib", "get_scheme", "get_src_prefix", @@ -482,13 +482,13 @@ def _looks_like_apple_library(path: str) -> bool: return path == f"/Library/Python/{get_major_minor_version()}/site-packages" -def get_prefixed_libs(prefix: str) -> List[str]: +def get_isolated_environment_lib_paths(prefix: str) -> List[str]: """Return the lib locations under ``prefix``.""" - new_pure, new_plat = _sysconfig.get_prefixed_libs(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_prefixed_libs(prefix) + 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 diff --git a/src/pip/_internal/locations/_distutils.py b/src/pip/_internal/locations/_distutils.py index c7712f016f5..a6fbcd2f09d 100644 --- a/src/pip/_internal/locations/_distutils.py +++ b/src/pip/_internal/locations/_distutils.py @@ -173,7 +173,7 @@ def get_platlib() -> str: return get_python_lib(plat_specific=True) -def get_prefixed_libs(prefix: str) -> Tuple[str, str]: +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 5c870c783b3..69821572081 100644 --- a/src/pip/_internal/locations/_sysconfig.py +++ b/src/pip/_internal/locations/_sysconfig.py @@ -213,7 +213,7 @@ def get_platlib() -> str: return sysconfig.get_paths()["platlib"] -def get_prefixed_libs(prefix: str) -> typing.Tuple[str, str]: +def get_isolated_environment_lib_paths(prefix: str) -> typing.Tuple[str, str]: vars = {"base": prefix, "platbase": prefix} if "venv" in sysconfig.get_scheme_names(): paths = sysconfig.get_paths(vars=vars, scheme="venv")