123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184 |
- import logging
- import pathlib
- import sys
- import sysconfig
- from typing import List, Optional
- from pip._internal.models.scheme import SCHEME_KEYS, Scheme
- from . import _distutils, _sysconfig
- from .base import (
- USER_CACHE_DIR,
- get_major_minor_version,
- get_src_prefix,
- site_packages,
- user_site,
- )
- __all__ = [
- "USER_CACHE_DIR",
- "get_bin_prefix",
- "get_bin_user",
- "get_major_minor_version",
- "get_platlib",
- "get_prefixed_libs",
- "get_purelib",
- "get_scheme",
- "get_src_prefix",
- "site_packages",
- "user_site",
- ]
- logger = logging.getLogger(__name__)
- def _default_base(*, user: bool) -> str:
- if user:
- base = sysconfig.get_config_var("userbase")
- else:
- base = sysconfig.get_config_var("base")
- assert base is not None
- return base
- def _warn_if_mismatch(old: pathlib.Path, new: pathlib.Path, *, key: str) -> bool:
- if old == new:
- return False
- issue_url = "https://github.com/pypa/pip/issues/9617"
- message = (
- "Value for %s does not match. Please report this to <%s>"
- "\ndistutils: %s"
- "\nsysconfig: %s"
- )
- logger.debug(message, key, issue_url, old, new)
- return True
- def _log_context(
- *,
- user: bool = False,
- home: Optional[str] = None,
- root: Optional[str] = None,
- prefix: Optional[str] = None,
- ) -> None:
- message = (
- "Additional context:" "\nuser = %r" "\nhome = %r" "\nroot = %r" "\nprefix = %r"
- )
- logger.debug(message, user, home, root, prefix)
- def get_scheme(
- dist_name, # type: str
- user=False, # type: bool
- home=None, # type: Optional[str]
- root=None, # type: Optional[str]
- isolated=False, # type: bool
- prefix=None, # type: Optional[str]
- ):
- # type: (...) -> Scheme
- old = _distutils.get_scheme(
- dist_name,
- user=user,
- home=home,
- root=root,
- isolated=isolated,
- prefix=prefix,
- )
- new = _sysconfig.get_scheme(
- dist_name,
- user=user,
- home=home,
- root=root,
- isolated=isolated,
- prefix=prefix,
- )
- base = prefix or home or _default_base(user=user)
- warned = []
- for k in SCHEME_KEYS:
- # Extra join because distutils can return relative paths.
- old_v = pathlib.Path(base, getattr(old, k))
- new_v = pathlib.Path(getattr(new, k))
- # distutils incorrectly put PyPy packages under ``site-packages/python``
- # in the ``posix_home`` scheme, but PyPy devs said they expect the
- # directory name to be ``pypy`` instead. So we treat this as a bug fix
- # and not warn about it. See bpo-43307 and python/cpython#24628.
- skip_pypy_special_case = (
- sys.implementation.name == "pypy"
- and home is not None
- and k in ("platlib", "purelib")
- and old_v.parent == new_v.parent
- and old_v.name == "python"
- and new_v.name == "pypy"
- )
- if skip_pypy_special_case:
- continue
- warned.append(_warn_if_mismatch(old_v, new_v, key=f"scheme.{k}"))
- if any(warned):
- _log_context(user=user, home=home, root=root, prefix=prefix)
- return old
- def get_bin_prefix():
- # type: () -> str
- old = _distutils.get_bin_prefix()
- new = _sysconfig.get_bin_prefix()
- if _warn_if_mismatch(pathlib.Path(old), pathlib.Path(new), key="bin_prefix"):
- _log_context()
- return old
- def get_bin_user():
- # type: () -> str
- return _sysconfig.get_scheme("", user=True).scripts
- def get_purelib():
- # type: () -> str
- """Return the default pure-Python lib location."""
- old = _distutils.get_purelib()
- new = _sysconfig.get_purelib()
- if _warn_if_mismatch(pathlib.Path(old), pathlib.Path(new), key="purelib"):
- _log_context()
- return old
- def get_platlib():
- # type: () -> str
- """Return the default platform-shared lib location."""
- old = _distutils.get_platlib()
- new = _sysconfig.get_platlib()
- if _warn_if_mismatch(pathlib.Path(old), pathlib.Path(new), key="platlib"):
- _log_context()
- return old
- def get_prefixed_libs(prefix):
- # type: (str) -> List[str]
- """Return the lib locations under ``prefix``."""
- old_pure, old_plat = _distutils.get_prefixed_libs(prefix)
- new_pure, new_plat = _sysconfig.get_prefixed_libs(prefix)
- warned = [
- _warn_if_mismatch(
- pathlib.Path(old_pure),
- pathlib.Path(new_pure),
- key="prefixed-purelib",
- ),
- _warn_if_mismatch(
- pathlib.Path(old_plat),
- pathlib.Path(new_plat),
- key="prefixed-platlib",
- ),
- ]
- if any(warned):
- _log_context(prefix=prefix)
- if old_pure == old_plat:
- return [old_pure]
- return [old_pure, old_plat]
|