Skip to content

Commit aaba499

Browse files
committed
Post a deprecation warning for distutils configs
Since we can't do anything about them in the transition (CPython is dropping support for those entirely), there's nothing we can do but to tell users to not use them. This also accounts for Homebrew and Linuxbrew for now. Hopefully they will come up with better solutions that don't trigger the location mismatch warning.
1 parent a2cbacf commit aaba499

File tree

2 files changed

+57
-18
lines changed

2 files changed

+57
-18
lines changed

src/pip/_internal/locations/__init__.py

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
from pip._internal.models.scheme import SCHEME_KEYS, Scheme
1010
from pip._internal.utils.compat import WINDOWS
11+
from pip._internal.utils.deprecation import deprecated
1112

1213
from . import _distutils, _sysconfig
1314
from .base import (
@@ -99,16 +100,20 @@ def _default_base(*, user: bool) -> str:
99100

100101

101102
@functools.lru_cache(maxsize=None)
102-
def _warn_if_mismatch(old: pathlib.Path, new: pathlib.Path, *, key: str) -> bool:
103-
if old == new:
104-
return False
103+
def _warn_mismatched(old: pathlib.Path, new: pathlib.Path, *, key: str) -> None:
105104
issue_url = "https://github.com/pypa/pip/issues/10151"
106105
message = (
107106
"Value for %s does not match. Please report this to <%s>"
108107
"\ndistutils: %s"
109108
"\nsysconfig: %s"
110109
)
111110
logger.log(_MISMATCH_LEVEL, message, key, issue_url, old, new)
111+
112+
113+
def _warn_if_mismatch(old: pathlib.Path, new: pathlib.Path, *, key: str) -> bool:
114+
if old == new:
115+
return False
116+
_warn_mismatched(old, new, key=key)
112117
return True
113118

114119

@@ -157,12 +162,15 @@ def get_scheme(
157162
)
158163

159164
base = prefix or home or _default_base(user=user)
160-
warned = []
165+
warning_contexts = []
161166
for k in SCHEME_KEYS:
162167
# Extra join because distutils can return relative paths.
163168
old_v = pathlib.Path(base, getattr(old, k))
164169
new_v = pathlib.Path(getattr(new, k))
165170

171+
if old_v == new_v:
172+
continue
173+
166174
# distutils incorrectly put PyPy packages under ``site-packages/python``
167175
# in the ``posix_home`` scheme, but PyPy devs said they expect the
168176
# directory name to be ``pypy`` instead. So we treat this as a bug fix
@@ -221,10 +229,38 @@ def get_scheme(
221229
if skip_sysconfig_abiflag_bug:
222230
continue
223231

224-
warned.append(_warn_if_mismatch(old_v, new_v, key=f"scheme.{k}"))
232+
warning_contexts.append((old_v, new_v, f"scheme.{k}"))
225233

226-
if any(warned):
227-
_log_context(user=user, home=home, root=root, prefix=prefix)
234+
if not warning_contexts:
235+
return old
236+
237+
# Check if this path mismatch is caused by distutils config files. Those
238+
# files will no longer work once we switch to sysconfig, so this raises a
239+
# deprecation message for them.
240+
default_old = _distutils.distutils_scheme(
241+
dist_name,
242+
user,
243+
home,
244+
root,
245+
isolated,
246+
prefix,
247+
ignore_config_files=True,
248+
)
249+
if any(default_old[k] != getattr(old, k) for k in SCHEME_KEYS):
250+
deprecated(
251+
"Configuring installation scheme with distutils config files "
252+
"is deprecated and will no longer work in the near future. If you "
253+
"are using a Homebrew or Linuxbrew Python, please see discussion "
254+
"at https://github.com/Homebrew/homebrew-core/issues/76621",
255+
replacement=None,
256+
gone_in=None,
257+
)
258+
return old
259+
260+
# Post warnings about this mismatch so user can report them back.
261+
for old_v, new_v, key in warning_contexts:
262+
_warn_mismatched(old_v, new_v, key=key)
263+
_log_context(user=user, home=home, root=root, prefix=prefix)
228264

229265
return old
230266

src/pip/_internal/locations/_distutils.py

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,15 @@
2121
logger = logging.getLogger(__name__)
2222

2323

24-
def _distutils_scheme(
24+
def distutils_scheme(
2525
dist_name: str,
2626
user: bool = False,
2727
home: str = None,
2828
root: str = None,
2929
isolated: bool = False,
3030
prefix: str = None,
31+
*,
32+
ignore_config_files: bool = False,
3133
) -> Dict[str, str]:
3234
"""
3335
Return a distutils install scheme
@@ -39,15 +41,16 @@ def _distutils_scheme(
3941
dist_args["script_args"] = ["--no-user-cfg"]
4042

4143
d = Distribution(dist_args)
42-
try:
43-
d.parse_config_files()
44-
except UnicodeDecodeError:
45-
# Typeshed does not include find_config_files() for some reason.
46-
paths = d.find_config_files() # type: ignore
47-
logger.warning(
48-
"Ignore distutils configs in %s due to encoding errors.",
49-
", ".join(os.path.basename(p) for p in paths),
50-
)
44+
if not ignore_config_files:
45+
try:
46+
d.parse_config_files()
47+
except UnicodeDecodeError:
48+
# Typeshed does not include find_config_files() for some reason.
49+
paths = d.find_config_files() # type: ignore
50+
logger.warning(
51+
"Ignore distutils configs in %s due to encoding errors.",
52+
", ".join(os.path.basename(p) for p in paths),
53+
)
5154
obj: Optional[DistutilsCommand] = None
5255
obj = d.get_command_obj("install", create=True)
5356
assert obj is not None
@@ -121,7 +124,7 @@ def get_scheme(
121124
:param prefix: indicates to use the "prefix" scheme and provides the
122125
base directory for the same
123126
"""
124-
scheme = _distutils_scheme(dist_name, user, home, root, isolated, prefix)
127+
scheme = distutils_scheme(dist_name, user, home, root, isolated, prefix)
125128
return Scheme(
126129
platlib=scheme["platlib"],
127130
purelib=scheme["purelib"],

0 commit comments

Comments
 (0)