From da478818c1c1d45770487f4346351413d92f61c9 Mon Sep 17 00:00:00 2001 From: Daniele Nicolodi Date: Sun, 27 Nov 2022 16:49:08 +0100 Subject: [PATCH 1/4] Fix isolated environment scripts path on Debian The scripts path was looked up passing explicitly the scheme to be used using "nt" on Windows and "posix_prefix" everywhere else. However, when the isolated build environment is created, packages are installed using the default scheme for the platform. On most platforms this works because normally "nt" and "posix_prefix" are the default schemes. However, Debian customizes sysconfig to use a "posix_local" scheme by default and under this scheme the scripts path does not match the one of the "posix_prefix" scheme. This results in scripts installed as part of the build dependencies not to be found during the build, as reported here https://github.com/mesonbuild/meson-python/issues/109 and here https://bugs.debian.org/1019293. The problem can be solved omitting to specify a scheme when looking up the scripts path. To future proof the path lookup, use the "venv" scheme if available as done in #11598. For uniformity use similar functions as used to lookup the library paths. --- news/11623.bugfix.rst | 1 + src/pip/_internal/build_env.py | 7 ++----- src/pip/_internal/locations/__init__.py | 5 +++++ src/pip/_internal/locations/_sysconfig.py | 16 ++++++++++++---- 4 files changed, 20 insertions(+), 9 deletions(-) create mode 100644 news/11623.bugfix.rst diff --git a/news/11623.bugfix.rst b/news/11623.bugfix.rst new file mode 100644 index 00000000000..45b8fe1928f --- /dev/null +++ b/news/11623.bugfix.rst @@ -0,0 +1 @@ +Fix scripts path in isolated build environment on Debian. diff --git a/src/pip/_internal/build_env.py b/src/pip/_internal/build_env.py index e67b868e8f4..24bfa870b07 100644 --- a/src/pip/_internal/build_env.py +++ b/src/pip/_internal/build_env.py @@ -8,7 +8,6 @@ import sys import textwrap from collections import OrderedDict -from sysconfig import get_paths from types import TracebackType from typing import TYPE_CHECKING, Iterable, List, Optional, Set, Tuple, Type @@ -19,6 +18,7 @@ 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, @@ -37,10 +37,7 @@ class _Prefix: def __init__(self, path: str) -> None: self.path = path self.setup = False - self.bin_dir = get_paths( - "nt" if os.name == "nt" else "posix_prefix", - vars={"base": path, "platbase": path}, - )["scripts"] + self.bin_dir = get_isolated_environment_bin_path(path) self.lib_dirs = get_isolated_environment_lib_paths(path) diff --git a/src/pip/_internal/locations/__init__.py b/src/pip/_internal/locations/__init__.py index 516bd607839..547bb803ce2 100644 --- a/src/pip/_internal/locations/__init__.py +++ b/src/pip/_internal/locations/__init__.py @@ -28,6 +28,7 @@ "get_major_minor_version", "get_platlib", "get_isolated_environment_lib_paths", + "get_isolated_environment_bin_path", "get_purelib", "get_scheme", "get_src_prefix", @@ -526,3 +527,7 @@ def get_isolated_environment_lib_paths(prefix: str) -> List[str]: _log_context(prefix=prefix) return old_lib_paths + + +def get_isolated_environment_bin_path(prefix: str) -> str: + return _sysconfig.get_isolated_environment_bin_path(prefix) diff --git a/src/pip/_internal/locations/_sysconfig.py b/src/pip/_internal/locations/_sysconfig.py index 69821572081..dfe2f0bd5a0 100644 --- a/src/pip/_internal/locations/_sysconfig.py +++ b/src/pip/_internal/locations/_sysconfig.py @@ -213,10 +213,18 @@ def get_platlib() -> str: return sysconfig.get_paths()["platlib"] -def get_isolated_environment_lib_paths(prefix: str) -> typing.Tuple[str, str]: +def _get_isolated_environment_paths(prefix: str) -> typing.Dict[str, str]: 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 sysconfig.get_paths(vars=vars, scheme="venv") + return sysconfig.get_paths(vars=vars) + + +def get_isolated_environment_lib_paths(prefix: str) -> typing.Tuple[str, str]: + paths = _get_isolated_environment_paths(prefix) return (paths["purelib"], paths["platlib"]) + + +def get_isolated_environment_bin_path(prefix: str) -> str: + paths = _get_isolated_environment_paths(prefix) + return paths["scripts"] From 77ef9f0bfd456a5cd1a3a969072a158e781962d3 Mon Sep 17 00:00:00 2001 From: Tzu-ping Chung Date: Wed, 28 Dec 2022 10:41:06 +0800 Subject: [PATCH 2/4] Avoid using built-in names as variable name --- src/pip/_internal/locations/_sysconfig.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pip/_internal/locations/_sysconfig.py b/src/pip/_internal/locations/_sysconfig.py index dfe2f0bd5a0..2bf5a1f444a 100644 --- a/src/pip/_internal/locations/_sysconfig.py +++ b/src/pip/_internal/locations/_sysconfig.py @@ -214,10 +214,10 @@ def get_platlib() -> str: def _get_isolated_environment_paths(prefix: str) -> typing.Dict[str, str]: - vars = {"base": prefix, "platbase": prefix} + variables = {"base": prefix, "platbase": prefix} if "venv" in sysconfig.get_scheme_names(): - return sysconfig.get_paths(vars=vars, scheme="venv") - return sysconfig.get_paths(vars=vars) + 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]: From 28e5eb99c813ede28f40f53213ae517b6535e38b Mon Sep 17 00:00:00 2001 From: Tzu-ping Chung Date: Wed, 28 Dec 2022 10:42:04 +0800 Subject: [PATCH 3/4] Avoid unnecessary indirection Since there's not equivalent of get_isolated_environment_bin_path for the distutils backend, the additional declaretion in the sysconfig backend is unnecessary. --- src/pip/_internal/locations/__init__.py | 2 +- src/pip/_internal/locations/_sysconfig.py | 9 ++------- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/src/pip/_internal/locations/__init__.py b/src/pip/_internal/locations/__init__.py index 547bb803ce2..815f8c22b15 100644 --- a/src/pip/_internal/locations/__init__.py +++ b/src/pip/_internal/locations/__init__.py @@ -530,4 +530,4 @@ def get_isolated_environment_lib_paths(prefix: str) -> List[str]: def get_isolated_environment_bin_path(prefix: str) -> str: - return _sysconfig.get_isolated_environment_bin_path(prefix) + return _sysconfig.get_isolated_environment_paths(prefix)["scripts"] diff --git a/src/pip/_internal/locations/_sysconfig.py b/src/pip/_internal/locations/_sysconfig.py index 2bf5a1f444a..38e400f94d4 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_isolated_environment_paths(prefix: str) -> typing.Dict[str, str]: +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") @@ -221,10 +221,5 @@ def _get_isolated_environment_paths(prefix: str) -> typing.Dict[str, str]: def get_isolated_environment_lib_paths(prefix: str) -> typing.Tuple[str, str]: - paths = _get_isolated_environment_paths(prefix) + paths = get_isolated_environment_paths(prefix) return (paths["purelib"], paths["platlib"]) - - -def get_isolated_environment_bin_path(prefix: str) -> str: - paths = _get_isolated_environment_paths(prefix) - return paths["scripts"] From a0c607ffbf481a67e23c33a38e956fed7d2025ff Mon Sep 17 00:00:00 2001 From: Tzu-ping Chung Date: Wed, 28 Dec 2022 10:44:51 +0800 Subject: [PATCH 4/4] Reorder __all__ The list is *almost* sorted alphabetically so let's make it fully so. --- src/pip/_internal/locations/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pip/_internal/locations/__init__.py b/src/pip/_internal/locations/__init__.py index 815f8c22b15..496844be142 100644 --- a/src/pip/_internal/locations/__init__.py +++ b/src/pip/_internal/locations/__init__.py @@ -25,10 +25,10 @@ "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_isolated_environment_lib_paths", - "get_isolated_environment_bin_path", "get_purelib", "get_scheme", "get_src_prefix",