Skip to content

Commit d8c5b7d

Browse files
committed
Detect "the other" Red Hat patch for Cygwin
1 parent c5332d5 commit d8c5b7d

File tree

1 file changed

+27
-6
lines changed

1 file changed

+27
-6
lines changed

src/pip/_internal/locations/__init__.py

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@
44
import pathlib
55
import sys
66
import sysconfig
7-
from typing import Dict, Iterator, List, Optional, Tuple
7+
from typing import Any, Dict, Iterator, List, Optional, Tuple
88

99
from pip._internal.models.scheme import SCHEME_KEYS, Scheme
1010
from pip._internal.utils.compat import WINDOWS
1111
from pip._internal.utils.deprecation import deprecated
12+
from pip._internal.utils.virtualenv import running_under_virtualenv
1213

1314
from . import _distutils, _sysconfig
1415
from .base import (
@@ -52,7 +53,7 @@ def _looks_like_red_hat_patched_platlib_purelib(scheme: Dict[str, str]) -> bool:
5253

5354

5455
@functools.lru_cache(maxsize=None)
55-
def _looks_like_red_hat_patched() -> bool:
56+
def _looks_like_red_hat_lib() -> bool:
5657
"""Red Hat patches platlib in unix_prefix and unix_home, but not purelib.
5758
5859
This is the only way I can see to tell a Red Hat-patched Python.
@@ -67,13 +68,33 @@ def _looks_like_red_hat_patched() -> bool:
6768

6869

6970
@functools.lru_cache(maxsize=None)
70-
def _looks_like_debian_patched() -> bool:
71+
def _looks_like_debian_scheme() -> bool:
7172
"""Debian adds two additional schemes."""
7273
from distutils.command.install import INSTALL_SCHEMES # type: ignore
7374

7475
return "deb_system" in INSTALL_SCHEMES and "unix_local" in INSTALL_SCHEMES
7576

7677

78+
@functools.lru_cache(maxsize=None)
79+
def _looks_like_red_hat_scheme() -> bool:
80+
"""Red Hat patches ``sys.prefix`` and ``sys.exec_prefix``.
81+
82+
Red Hat's ``00251-change-user-install-location.patch`` changes the install
83+
command's ``prefix`` and ``exec_prefix`` to append ``"/local"``. This is
84+
(fortunately?) done quite unconditionally, so we create a default command
85+
object without any configuration to detect this.
86+
"""
87+
from distutils.command.install import install
88+
from distutils.dist import Distribution
89+
90+
cmd: Any = install(Distribution())
91+
cmd.finalize_options()
92+
return (
93+
cmd.exec_prefix == f"{os.path.normpath(sys.exec_prefix)}/local"
94+
and cmd.prefix == f"{os.path.normpath(sys.prefix)}/local"
95+
)
96+
97+
7798
def _fix_abiflags(parts: Tuple[str]) -> Iterator[str]:
7899
ldversion = sysconfig.get_config_var("LDVERSION")
79100
abiflags: str = getattr(sys, "abiflags", None)
@@ -201,19 +222,19 @@ def get_scheme(
201222

202223
# On Red Hat and derived Linux distributions, distutils is patched to
203224
# use "lib64" instead of "lib" for platlib.
204-
if k == "platlib" and _looks_like_red_hat_patched():
225+
if k == "platlib" and _looks_like_red_hat_lib():
205226
continue
206227

207228
# Both Debian and Red Hat patch Python to place the system site under
208229
# /usr/local instead of /usr. Debian also places lib in dist-packages
209230
# instead of site-packages, but the /usr/local check should cover it.
210231
skip_linux_system_special_case = (
211-
not (user or home or prefix)
232+
not (user or home or prefix or running_under_virtualenv())
212233
and old_v.parts[1:3] == ("usr", "local")
213234
and len(new_v.parts) > 1
214235
and new_v.parts[1] == "usr"
215236
and (len(new_v.parts) < 3 or new_v.parts[2] != "local")
216-
and (_looks_like_red_hat_patched() or _looks_like_debian_patched())
237+
and (_looks_like_red_hat_scheme() or _looks_like_debian_scheme())
217238
)
218239
if skip_linux_system_special_case:
219240
continue

0 commit comments

Comments
 (0)