Skip to content

Commit 9a0d930

Browse files
dnicolodipradyunsg
authored andcommitted
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.
1 parent e6deb9b commit 9a0d930

File tree

5 files changed

+14
-96
lines changed

5 files changed

+14
-96
lines changed

news/11740.bugfix.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Improve handling of isolated build environments on platforms that
2+
customize the Python's installation schemes, such as Debian and
3+
Homebrew.

src/pip/_internal/build_env.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,15 @@
99
import textwrap
1010
from collections import OrderedDict
1111
from types import TracebackType
12-
from typing import TYPE_CHECKING, Iterable, List, Optional, Set, Tuple, Type
12+
from typing import TYPE_CHECKING, Iterable, List, Optional, Set, Tuple, Type, Union
1313

1414
from pip._vendor.certifi import where
1515
from pip._vendor.packaging.requirements import Requirement
1616
from pip._vendor.packaging.version import Version
1717

1818
from pip import __file__ as pip_location
1919
from pip._internal.cli.spinners import open_spinner
20-
from pip._internal.locations import (
21-
get_isolated_environment_bin_path,
22-
get_isolated_environment_lib_paths,
23-
get_platlib,
24-
get_purelib,
25-
)
20+
from pip._internal.locations import get_platlib, get_purelib, get_scheme
2621
from pip._internal.metadata import get_default_environment, get_environment
2722
from pip._internal.utils.subprocess import call_subprocess
2823
from pip._internal.utils.temp_dir import TempDirectory, tempdir_kinds
@@ -33,12 +28,17 @@
3328
logger = logging.getLogger(__name__)
3429

3530

31+
def _dedup(a: str, b: str) -> Union[Tuple[str], Tuple[str, str]]:
32+
return (a, b) if a != b else (a,)
33+
34+
3635
class _Prefix:
3736
def __init__(self, path: str) -> None:
3837
self.path = path
3938
self.setup = False
40-
self.bin_dir = get_isolated_environment_bin_path(path)
41-
self.lib_dirs = get_isolated_environment_lib_paths(path)
39+
scheme = get_scheme("", prefix=path)
40+
self.bin_dir = scheme.scripts
41+
self.lib_dirs = _dedup(scheme.purelib, scheme.platlib)
4242

4343

4444
def get_runnable_pip() -> str:

src/pip/_internal/locations/__init__.py

Lines changed: 1 addition & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import pathlib
55
import sys
66
import sysconfig
7-
from typing import Any, Dict, Generator, List, Optional, Tuple
7+
from typing import Any, Dict, Generator, Optional, Tuple
88

99
from pip._internal.models.scheme import SCHEME_KEYS, Scheme
1010
from pip._internal.utils.compat import WINDOWS
@@ -25,8 +25,6 @@
2525
"USER_CACHE_DIR",
2626
"get_bin_prefix",
2727
"get_bin_user",
28-
"get_isolated_environment_bin_path",
29-
"get_isolated_environment_lib_paths",
3028
"get_major_minor_version",
3129
"get_platlib",
3230
"get_purelib",
@@ -467,67 +465,3 @@ def get_platlib() -> str:
467465
if _warn_if_mismatch(pathlib.Path(old), pathlib.Path(new), key="platlib"):
468466
_log_context()
469467
return old
470-
471-
472-
def _deduplicated(v1: str, v2: str) -> List[str]:
473-
"""Deduplicate values from a list."""
474-
if v1 == v2:
475-
return [v1]
476-
return [v1, v2]
477-
478-
479-
def _looks_like_apple_library(path: str) -> bool:
480-
"""Apple patches sysconfig to *always* look under */Library/Python*."""
481-
if sys.platform[:6] != "darwin":
482-
return False
483-
return path == f"/Library/Python/{get_major_minor_version()}/site-packages"
484-
485-
486-
def get_isolated_environment_lib_paths(prefix: str) -> List[str]:
487-
"""Return the lib locations under ``prefix``."""
488-
new_pure, new_plat = _sysconfig.get_isolated_environment_lib_paths(prefix)
489-
if _USE_SYSCONFIG:
490-
return _deduplicated(new_pure, new_plat)
491-
492-
old_pure, old_plat = _distutils.get_isolated_environment_lib_paths(prefix)
493-
old_lib_paths = _deduplicated(old_pure, old_plat)
494-
495-
# Apple's Python (shipped with Xcode and Command Line Tools) hard-code
496-
# platlib and purelib to '/Library/Python/X.Y/site-packages'. This will
497-
# cause serious build isolation bugs when Apple starts shipping 3.10 because
498-
# pip will install build backends to the wrong location. This tells users
499-
# who is at fault so Apple may notice it and fix the issue in time.
500-
if all(_looks_like_apple_library(p) for p in old_lib_paths):
501-
deprecated(
502-
reason=(
503-
"Python distributed by Apple's Command Line Tools incorrectly "
504-
"patches sysconfig to always point to '/Library/Python'. This "
505-
"will cause build isolation to operate incorrectly on Python "
506-
"3.10 or later. Please help report this to Apple so they can "
507-
"fix this. https://developer.apple.com/bug-reporting/"
508-
),
509-
replacement=None,
510-
gone_in=None,
511-
)
512-
return old_lib_paths
513-
514-
warned = [
515-
_warn_if_mismatch(
516-
pathlib.Path(old_pure),
517-
pathlib.Path(new_pure),
518-
key="prefixed-purelib",
519-
),
520-
_warn_if_mismatch(
521-
pathlib.Path(old_plat),
522-
pathlib.Path(new_plat),
523-
key="prefixed-platlib",
524-
),
525-
]
526-
if any(warned):
527-
_log_context(prefix=prefix)
528-
529-
return old_lib_paths
530-
531-
532-
def get_isolated_environment_bin_path(prefix: str) -> str:
533-
return _sysconfig.get_isolated_environment_paths(prefix)["scripts"]

src/pip/_internal/locations/_distutils.py

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
from distutils.command.install import SCHEME_KEYS
2222
from distutils.command.install import install as distutils_install_command
2323
from distutils.sysconfig import get_python_lib
24-
from typing import Dict, List, Optional, Tuple, Union, cast
24+
from typing import Dict, List, Optional, Union, cast
2525

2626
from pip._internal.models.scheme import Scheme
2727
from pip._internal.utils.compat import WINDOWS
@@ -171,10 +171,3 @@ def get_purelib() -> str:
171171

172172
def get_platlib() -> str:
173173
return get_python_lib(plat_specific=True)
174-
175-
176-
def get_isolated_environment_lib_paths(prefix: str) -> Tuple[str, str]:
177-
return (
178-
get_python_lib(plat_specific=False, prefix=prefix),
179-
get_python_lib(plat_specific=True, prefix=prefix),
180-
)

src/pip/_internal/locations/_sysconfig.py

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -211,15 +211,3 @@ def get_purelib() -> str:
211211

212212
def get_platlib() -> str:
213213
return sysconfig.get_paths()["platlib"]
214-
215-
216-
def get_isolated_environment_paths(prefix: str) -> typing.Dict[str, str]:
217-
variables = {"base": prefix, "platbase": prefix}
218-
if "venv" in sysconfig.get_scheme_names():
219-
return sysconfig.get_paths(vars=variables, scheme="venv")
220-
return sysconfig.get_paths(vars=variables)
221-
222-
223-
def get_isolated_environment_lib_paths(prefix: str) -> typing.Tuple[str, str]:
224-
paths = get_isolated_environment_paths(prefix)
225-
return (paths["purelib"], paths["platlib"])

0 commit comments

Comments
 (0)