Let us walk on the 3-isogeny graph
Loading...
Searching...
No Matches
pip._internal.locations Namespace Reference

Namespaces

namespace  _distutils
 
namespace  _sysconfig
 
namespace  base
 

Functions

bool _should_use_sysconfig ()
 
bool _looks_like_bpo_44860 ()
 
bool _looks_like_red_hat_patched_platlib_purelib (Dict[str, str] scheme)
 
bool _looks_like_red_hat_lib ()
 
bool _looks_like_debian_scheme ()
 
bool _looks_like_red_hat_scheme ()
 
bool _looks_like_slackware_scheme ()
 
bool _looks_like_msys2_mingw_scheme ()
 
Generator[str, None, None_fix_abiflags (Tuple[str] parts)
 
None _warn_mismatched (pathlib.Path old, pathlib.Path new, *str key)
 
bool _warn_if_mismatch (pathlib.Path old, pathlib.Path new, *str key)
 
None _log_context (*bool user=False, Optional[str] home=None, Optional[str] root=None, Optional[str] prefix=None)
 
Scheme get_scheme (str dist_name, bool user=False, Optional[str] home=None, Optional[str] root=None, bool isolated=False, Optional[str] prefix=None)
 
str get_bin_prefix ()
 
str get_bin_user ()
 
bool _looks_like_deb_system_dist_packages (str value)
 
str get_purelib ()
 
str get_platlib ()
 

Variables

 logger = logging.getLogger(__name__)
 
str _PLATLIBDIR = getattr(sys, "platlibdir", "lib")
 
tuple _USE_SYSCONFIG_DEFAULT = (3, 10)
 
bool _USE_SYSCONFIG = _should_use_sysconfig()
 
 _MISMATCH_LEVEL = logging.WARNING
 

Function Documentation

◆ _fix_abiflags()

Generator[str, None, None] _fix_abiflags ( Tuple[str]  parts)
protected

Definition at line 177 of file __init__.py.

177def _fix_abiflags(parts: Tuple[str]) -> Generator[str, None, None]:
178 ldversion = sysconfig.get_config_var("LDVERSION")
179 abiflags = getattr(sys, "abiflags", None)
180
181 # LDVERSION does not end with sys.abiflags. Just return the path unchanged.
182 if not ldversion or not abiflags or not ldversion.endswith(abiflags):
183 yield from parts
184 return
185
186 # Strip sys.abiflags from LDVERSION-based path components.
187 for part in parts:
188 if part.endswith(ldversion):
189 part = part[: (0 - len(abiflags))]
190 yield part
191
192
193@functools.lru_cache(maxsize=None)
for i

References i.

Referenced by pip._internal.locations.get_scheme().

Here is the caller graph for this function:

◆ _log_context()

None _log_context ( *bool   user = False,
Optional[str]   home = None,
Optional[str]   root = None,
Optional[str]   prefix = None 
)
protected

Definition at line 212 of file __init__.py.

218) -> None:
219 parts = [
220 "Additional context:",
221 "user = %r",
222 "home = %r",
223 "root = %r",
224 "prefix = %r",
225 ]
226
227 logger.log(_MISMATCH_LEVEL, "\n".join(parts), user, home, root, prefix)
228
229

References i.

Referenced by pip._internal.locations.get_bin_prefix(), pip._internal.locations.get_platlib(), pip._internal.locations.get_purelib(), and pip._internal.locations.get_scheme().

Here is the caller graph for this function:

◆ _looks_like_bpo_44860()

bool _looks_like_bpo_44860 ( )
protected
The resolution to bpo-44860 will change this incorrect platlib.

See <https://bugs.python.org/issue44860>.

Definition at line 76 of file __init__.py.

76def _looks_like_bpo_44860() -> bool:
77 """The resolution to bpo-44860 will change this incorrect platlib.
78
79 See <https://bugs.python.org/issue44860>.
80 """
81 from distutils.command.install import INSTALL_SCHEMES
82
83 try:
84 unix_user_platlib = INSTALL_SCHEMES["unix_user"]["platlib"]
85 except KeyError:
86 return False
87 return unix_user_platlib == "$usersite"
88
89

References i.

Referenced by pip._internal.locations.get_scheme().

Here is the caller graph for this function:

◆ _looks_like_deb_system_dist_packages()

bool _looks_like_deb_system_dist_packages ( str  value)
protected
Check if the value is Debian's APT-controlled dist-packages.

Debian's ``distutils.sysconfig.get_python_lib()`` implementation returns the
default package path controlled by APT, but does not patch ``sysconfig`` to
do the same. This is similar to the bug worked around in ``get_scheme()``,
but here the default is ``deb_system`` instead of ``unix_local``. Ultimately
we can't do anything about this Debian bug, and this detection allows us to
skip the warning when needed.

Definition at line 423 of file __init__.py.

423def _looks_like_deb_system_dist_packages(value: str) -> bool:
424 """Check if the value is Debian's APT-controlled dist-packages.
425
426 Debian's ``distutils.sysconfig.get_python_lib()`` implementation returns the
427 default package path controlled by APT, but does not patch ``sysconfig`` to
428 do the same. This is similar to the bug worked around in ``get_scheme()``,
429 but here the default is ``deb_system`` instead of ``unix_local``. Ultimately
430 we can't do anything about this Debian bug, and this detection allows us to
431 skip the warning when needed.
432 """
433 if not _looks_like_debian_scheme():
434 return False
435 if value == "/usr/lib/python3/dist-packages":
436 return True
437 return False
438
439

References pip._internal.locations._looks_like_debian_scheme().

Referenced by pip._internal.locations.get_platlib(), and pip._internal.locations.get_purelib().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _looks_like_debian_scheme()

bool _looks_like_debian_scheme ( )
protected
Debian adds two additional schemes.

Definition at line 116 of file __init__.py.

116def _looks_like_debian_scheme() -> bool:
117 """Debian adds two additional schemes."""
118 from distutils.command.install import INSTALL_SCHEMES
119
120 return "deb_system" in INSTALL_SCHEMES and "unix_local" in INSTALL_SCHEMES
121
122
123@functools.lru_cache(maxsize=None)

References i.

Referenced by pip._internal.locations._looks_like_deb_system_dist_packages(), and pip._internal.locations.get_scheme().

Here is the caller graph for this function:

◆ _looks_like_msys2_mingw_scheme()

bool _looks_like_msys2_mingw_scheme ( )
protected
MSYS2 patches distutils and sysconfig to use a UNIX-like scheme.

However, MSYS2 incorrectly patches sysconfig ``nt`` scheme. The fix is
likely going to be included in their 3.10 release, so we ignore the warning.
See msys2/MINGW-packages#9319.

MSYS2 MINGW's patch uses lowercase ``"lib"`` instead of the usual uppercase,
and is missing the final ``"site-packages"``.

Definition at line 160 of file __init__.py.

160def _looks_like_msys2_mingw_scheme() -> bool:
161 """MSYS2 patches distutils and sysconfig to use a UNIX-like scheme.
162
163 However, MSYS2 incorrectly patches sysconfig ``nt`` scheme. The fix is
164 likely going to be included in their 3.10 release, so we ignore the warning.
165 See msys2/MINGW-packages#9319.
166
167 MSYS2 MINGW's patch uses lowercase ``"lib"`` instead of the usual uppercase,
168 and is missing the final ``"site-packages"``.
169 """
170 paths = sysconfig.get_paths("nt", expand=False)
171 return all(
172 "Lib" not in p and "lib" in p and not p.endswith("site-packages")
173 for p in (paths[key] for key in ("platlib", "purelib"))
174 )
175
176

References i.

Referenced by pip._internal.locations.get_scheme().

Here is the caller graph for this function:

◆ _looks_like_red_hat_lib()

bool _looks_like_red_hat_lib ( )
protected
Red Hat patches platlib in unix_prefix and unix_home, but not purelib.

This is the only way I can see to tell a Red Hat-patched Python.

Definition at line 101 of file __init__.py.

101def _looks_like_red_hat_lib() -> bool:
102 """Red Hat patches platlib in unix_prefix and unix_home, but not purelib.
103
104 This is the only way I can see to tell a Red Hat-patched Python.
105 """
106 from distutils.command.install import INSTALL_SCHEMES
107
108 return all(
109 k in INSTALL_SCHEMES
110 and _looks_like_red_hat_patched_platlib_purelib(INSTALL_SCHEMES[k])
111 for k in ("unix_prefix", "unix_home")
112 )
113
114
115@functools.lru_cache(maxsize=None)

References pip._internal.locations._looks_like_red_hat_patched_platlib_purelib(), and i.

Referenced by pip._internal.locations.get_scheme().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _looks_like_red_hat_patched_platlib_purelib()

bool _looks_like_red_hat_patched_platlib_purelib ( Dict[str, str]  scheme)
protected

Definition at line 90 of file __init__.py.

90def _looks_like_red_hat_patched_platlib_purelib(scheme: Dict[str, str]) -> bool:
91 platlib = scheme["platlib"]
92 if "/$platlibdir/" in platlib:
93 platlib = platlib.replace("/$platlibdir/", f"/{_PLATLIBDIR}/")
94 if "/lib64/" not in platlib:
95 return False
96 unpatched = platlib.replace("/lib64/", "/lib/")
97 return unpatched.replace("$platbase/", "$base/") == scheme["purelib"]
98
99
100@functools.lru_cache(maxsize=None)

References i.

Referenced by pip._internal.locations._looks_like_red_hat_lib().

Here is the caller graph for this function:

◆ _looks_like_red_hat_scheme()

bool _looks_like_red_hat_scheme ( )
protected
Red Hat patches ``sys.prefix`` and ``sys.exec_prefix``.

Red Hat's ``00251-change-user-install-location.patch`` changes the install
command's ``prefix`` and ``exec_prefix`` to append ``"/local"``. This is
(fortunately?) done quite unconditionally, so we create a default command
object without any configuration to detect this.

Definition at line 124 of file __init__.py.

124def _looks_like_red_hat_scheme() -> bool:
125 """Red Hat patches ``sys.prefix`` and ``sys.exec_prefix``.
126
127 Red Hat's ``00251-change-user-install-location.patch`` changes the install
128 command's ``prefix`` and ``exec_prefix`` to append ``"/local"``. This is
129 (fortunately?) done quite unconditionally, so we create a default command
130 object without any configuration to detect this.
131 """
132 from distutils.command.install import install
133 from distutils.dist import Distribution
134
135 cmd: Any = install(Distribution())
137 return (
138 cmd.exec_prefix == f"{os.path.normpath(sys.exec_prefix)}/local"
139 and cmd.prefix == f"{os.path.normpath(sys.prefix)}/local"
140 )
141
142
143@functools.lru_cache(maxsize=None)

References i.

Referenced by pip._internal.locations.get_scheme().

Here is the caller graph for this function:

◆ _looks_like_slackware_scheme()

bool _looks_like_slackware_scheme ( )
protected
Slackware patches sysconfig but fails to patch distutils and site.

Slackware changes sysconfig's user scheme to use ``"lib64"`` for the lib
path, but does not do the same to the site module.

Definition at line 144 of file __init__.py.

144def _looks_like_slackware_scheme() -> bool:
145 """Slackware patches sysconfig but fails to patch distutils and site.
146
147 Slackware changes sysconfig's user scheme to use ``"lib64"`` for the lib
148 path, but does not do the same to the site module.
149 """
150 if user_site is None: # User-site not available.
151 return False
152 try:
153 paths = sysconfig.get_paths(scheme="posix_user", expand=False)
154 except KeyError: # User-site not available.
155 return False
156 return "/lib64/" in paths["purelib"] and "/lib64/" not in user_site
157
158
159@functools.lru_cache(maxsize=None)

References i.

Referenced by pip._internal.locations.get_scheme().

Here is the caller graph for this function:

◆ _should_use_sysconfig()

bool _should_use_sysconfig ( )
protected
This function determines the value of _USE_SYSCONFIG.

By default, pip uses sysconfig on Python 3.10+.
But Python distributors can override this decision by setting:
    sysconfig._PIP_USE_SYSCONFIG = True / False
Rationale in https://github.com/pypa/pip/issues/10647

This is a function for testability, but should be constant during any one
run.

Definition at line 46 of file __init__.py.

46def _should_use_sysconfig() -> bool:
47 """This function determines the value of _USE_SYSCONFIG.
48
49 By default, pip uses sysconfig on Python 3.10+.
50 But Python distributors can override this decision by setting:
51 sysconfig._PIP_USE_SYSCONFIG = True / False
52 Rationale in https://github.com/pypa/pip/issues/10647
53
54 This is a function for testability, but should be constant during any one
55 run.
56 """
57 return bool(getattr(sysconfig, "_PIP_USE_SYSCONFIG", _USE_SYSCONFIG_DEFAULT))
58
59

References i.

◆ _warn_if_mismatch()

bool _warn_if_mismatch ( pathlib.Path  old,
pathlib.Path  new,
*str  key 
)
protected

Definition at line 204 of file __init__.py.

204def _warn_if_mismatch(old: pathlib.Path, new: pathlib.Path, *, key: str) -> bool:
205 if old == new:
206 return False
207 _warn_mismatched(old, new, key=key)
208 return True
209
210
211@functools.lru_cache(maxsize=None)

References pip._internal.locations._warn_mismatched(), and i.

Referenced by pip._internal.locations.get_bin_prefix(), pip._internal.locations.get_platlib(), and pip._internal.locations.get_purelib().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _warn_mismatched()

None _warn_mismatched ( pathlib.Path  old,
pathlib.Path  new,
*str  key 
)
protected

Definition at line 194 of file __init__.py.

194def _warn_mismatched(old: pathlib.Path, new: pathlib.Path, *, key: str) -> None:
195 issue_url = "https://github.com/pypa/pip/issues/10151"
196 message = (
197 "Value for %s does not match. Please report this to <%s>"
198 "\ndistutils: %s"
199 "\nsysconfig: %s"
200 )
201 logger.log(_MISMATCH_LEVEL, message, key, issue_url, old, new)
202
203

References i.

Referenced by pip._internal.locations._warn_if_mismatch(), and pip._internal.locations.get_scheme().

Here is the caller graph for this function:

◆ get_bin_prefix()

str get_bin_prefix ( )

Definition at line 408 of file __init__.py.

408def get_bin_prefix() -> str:
410 if _USE_SYSCONFIG:
411 return new
412
414 if _warn_if_mismatch(pathlib.Path(old), pathlib.Path(new), key="bin_prefix"):
415 _log_context()
416 return old
417
418

References pip._internal.locations._log_context(), pip._internal.locations._warn_if_mismatch(), and i.

Here is the call graph for this function:

◆ get_bin_user()

str get_bin_user ( )

Definition at line 419 of file __init__.py.

419def get_bin_user() -> str:
420 return _sysconfig.get_scheme("", user=True).scripts
421
422

References i.

◆ get_platlib()

str get_platlib ( )
Return the default platform-shared lib location.

Definition at line 454 of file __init__.py.

454def get_platlib() -> str:
455 """Return the default platform-shared lib location."""
457 if _USE_SYSCONFIG:
458 return new
459
460 from . import _distutils
461
463 if _looks_like_deb_system_dist_packages(old):
464 return old
465 if _warn_if_mismatch(pathlib.Path(old), pathlib.Path(new), key="platlib"):
466 _log_context()
467 return old

References pip._internal.locations._log_context(), pip._internal.locations._looks_like_deb_system_dist_packages(), pip._internal.locations._warn_if_mismatch(), and i.

Here is the call graph for this function:

◆ get_purelib()

str get_purelib ( )
Return the default pure-Python lib location.

Definition at line 440 of file __init__.py.

440def get_purelib() -> str:
441 """Return the default pure-Python lib location."""
443 if _USE_SYSCONFIG:
444 return new
445
447 if _looks_like_deb_system_dist_packages(old):
448 return old
449 if _warn_if_mismatch(pathlib.Path(old), pathlib.Path(new), key="purelib"):
450 _log_context()
451 return old
452
453

References pip._internal.locations._log_context(), pip._internal.locations._looks_like_deb_system_dist_packages(), pip._internal.locations._warn_if_mismatch(), and i.

Here is the call graph for this function:

◆ get_scheme()

Scheme get_scheme ( str  dist_name,
bool   user = False,
Optional[str]   home = None,
Optional[str]   root = None,
bool   isolated = False,
Optional[str]   prefix = None 
)

Definition at line 230 of file __init__.py.

237) -> Scheme:
239 dist_name,
240 user=user,
241 home=home,
242 root=root,
243 isolated=isolated,
244 prefix=prefix,
245 )
246 if _USE_SYSCONFIG:
247 return new
248
250 dist_name,
251 user=user,
252 home=home,
253 root=root,
254 isolated=isolated,
255 prefix=prefix,
256 )
257
258 warning_contexts = []
259 for k in SCHEME_KEYS:
260 old_v = pathlib.Path(getattr(old, k))
261 new_v = pathlib.Path(getattr(new, k))
262
263 if old_v == new_v:
264 continue
265
266 # distutils incorrectly put PyPy packages under ``site-packages/python``
267 # in the ``posix_home`` scheme, but PyPy devs said they expect the
268 # directory name to be ``pypy`` instead. So we treat this as a bug fix
269 # and not warn about it. See bpo-43307 and python/cpython#24628.
270 skip_pypy_special_case = (
272 and home is not None
273 and k in ("platlib", "purelib")
275 and old_v.name.startswith("python")
276 and new_v.name.startswith("pypy")
277 )
278 if skip_pypy_special_case:
279 continue
280
281 # sysconfig's ``osx_framework_user`` does not include ``pythonX.Y`` in
282 # the ``include`` value, but distutils's ``headers`` does. We'll let
283 # CPython decide whether this is a bug or feature. See bpo-43948.
284 skip_osx_framework_user_special_case = (
285 user
286 and is_osx_framework()
287 and k == "headers"
289 and old_v.parent.name.startswith("python")
290 )
291 if skip_osx_framework_user_special_case:
292 continue
293
294 # On Red Hat and derived Linux distributions, distutils is patched to
295 # use "lib64" instead of "lib" for platlib.
296 if k == "platlib" and _looks_like_red_hat_lib():
297 continue
298
299 # On Python 3.9+, sysconfig's posix_user scheme sets platlib against
300 # sys.platlibdir, but distutils's unix_user incorrectly coninutes
301 # using the same $usersite for both platlib and purelib. This creates a
302 # mismatch when sys.platlibdir is not "lib".
303 skip_bpo_44860 = (
304 user
305 and k == "platlib"
306 and not WINDOWS
307 and sys.version_info >= (3, 9)
308 and _PLATLIBDIR != "lib"
309 and _looks_like_bpo_44860()
310 )
311 if skip_bpo_44860:
312 continue
313
314 # Slackware incorrectly patches posix_user to use lib64 instead of lib,
315 # but not usersite to match the location.
316 skip_slackware_user_scheme = (
317 user
318 and k in ("platlib", "purelib")
319 and not WINDOWS
320 and _looks_like_slackware_scheme()
321 )
322 if skip_slackware_user_scheme:
323 continue
324
325 # Both Debian and Red Hat patch Python to place the system site under
326 # /usr/local instead of /usr. Debian also places lib in dist-packages
327 # instead of site-packages, but the /usr/local check should cover it.
328 skip_linux_system_special_case = (
329 not (user or home or prefix or running_under_virtualenv())
330 and old_v.parts[1:3] == ("usr", "local")
331 and len(new_v.parts) > 1
332 and new_v.parts[1] == "usr"
333 and (len(new_v.parts) < 3 or new_v.parts[2] != "local")
334 and (_looks_like_red_hat_scheme() or _looks_like_debian_scheme())
335 )
336 if skip_linux_system_special_case:
337 continue
338
339 # On Python 3.7 and earlier, sysconfig does not include sys.abiflags in
340 # the "pythonX.Y" part of the path, but distutils does.
341 skip_sysconfig_abiflag_bug = (
342 sys.version_info < (3, 8)
343 and not WINDOWS
344 and k in ("headers", "platlib", "purelib")
345 and tuple(_fix_abiflags(old_v.parts)) == new_v.parts
346 )
347 if skip_sysconfig_abiflag_bug:
348 continue
349
350 # MSYS2 MINGW's sysconfig patch does not include the "site-packages"
351 # part of the path. This is incorrect and will be fixed in MSYS.
352 skip_msys2_mingw_bug = (
353 WINDOWS and k in ("platlib", "purelib") and _looks_like_msys2_mingw_scheme()
354 )
355 if skip_msys2_mingw_bug:
356 continue
357
358 # CPython's POSIX install script invokes pip (via ensurepip) against the
359 # interpreter located in the source tree, not the install site. This
360 # triggers special logic in sysconfig that's not present in distutils.
361 # https://github.com/python/cpython/blob/8c21941ddaf/Lib/sysconfig.py#L178-L194
362 skip_cpython_build = (
363 sysconfig.is_python_build(check_home=True)
364 and not WINDOWS
365 and k in ("headers", "include", "platinclude")
366 )
367 if skip_cpython_build:
368 continue
369
370 warning_contexts.append((old_v, new_v, f"scheme.{k}"))
371
372 if not warning_contexts:
373 return old
374
375 # Check if this path mismatch is caused by distutils config files. Those
376 # files will no longer work once we switch to sysconfig, so this raises a
377 # deprecation message for them.
378 default_old = _distutils.distutils_scheme(
379 dist_name,
380 user,
381 home,
382 root,
383 isolated,
384 prefix,
385 ignore_config_files=True,
386 )
387 if any(default_old[k] != getattr(old, k) for k in SCHEME_KEYS):
388 deprecated(
389 reason=(
390 "Configuring installation scheme with distutils config files "
391 "is deprecated and will no longer work in the near future. If you "
392 "are using a Homebrew or Linuxbrew Python, please see discussion "
393 "at https://github.com/Homebrew/homebrew-core/issues/76621"
394 ),
395 replacement=None,
396 gone_in=None,
397 )
398 return old
399
400 # Post warnings about this mismatch so user can report them back.
401 for old_v, new_v, key in warning_contexts:
402 _warn_mismatched(old_v, new_v, key=key)
403 _log_context(user=user, home=home, root=root, prefix=prefix)
404
405 return old
406
407

References pip._internal.locations._fix_abiflags(), pip._internal.locations._log_context(), pip._internal.locations._looks_like_bpo_44860(), pip._internal.locations._looks_like_debian_scheme(), pip._internal.locations._looks_like_msys2_mingw_scheme(), pip._internal.locations._looks_like_red_hat_lib(), pip._internal.locations._looks_like_red_hat_scheme(), pip._internal.locations._looks_like_slackware_scheme(), pip._internal.locations._warn_mismatched(), and i.

Here is the call graph for this function:

Variable Documentation

◆ _MISMATCH_LEVEL

_MISMATCH_LEVEL = logging.WARNING
protected

Definition at line 71 of file __init__.py.

◆ _PLATLIBDIR

str _PLATLIBDIR = getattr(sys, "platlibdir", "lib")
protected

Definition at line 41 of file __init__.py.

◆ _USE_SYSCONFIG

bool _USE_SYSCONFIG = _should_use_sysconfig()
protected

Definition at line 60 of file __init__.py.

◆ _USE_SYSCONFIG_DEFAULT

tuple _USE_SYSCONFIG_DEFAULT = (3, 10)
protected

Definition at line 43 of file __init__.py.

◆ logger

logger = logging.getLogger(__name__)

Definition at line 38 of file __init__.py.