[pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci
This commit is contained in:
pre-commit-ci[bot] 2024-04-13 00:00:18 +00:00
parent 72ad6dc953
commit f4cd1ba0d6
813 changed files with 66015 additions and 58839 deletions

View file

@ -1,45 +1,52 @@
from __future__ import annotations
import functools
import logging
import os
import pathlib
import sys
import sysconfig
from typing import Any, Dict, Iterator, List, Optional, Tuple
from typing import Any
from typing import Dict
from typing import Iterator
from typing import List
from typing import Optional
from typing import Tuple
from pip._internal.models.scheme import SCHEME_KEYS, Scheme
from pip._internal.models.scheme import Scheme
from pip._internal.models.scheme import SCHEME_KEYS
from pip._internal.utils.compat import WINDOWS
from pip._internal.utils.deprecation import deprecated
from pip._internal.utils.virtualenv import running_under_virtualenv
from . import _distutils, _sysconfig
from .base import (
USER_CACHE_DIR,
get_major_minor_version,
get_src_prefix,
is_osx_framework,
site_packages,
user_site,
)
from . import _distutils
from . import _sysconfig
from .base import get_major_minor_version
from .base import get_src_prefix
from .base import is_osx_framework
from .base import site_packages
from .base import USER_CACHE_DIR
from .base import 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",
'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__)
_PLATLIBDIR: str = getattr(sys, "platlibdir", "lib")
_PLATLIBDIR: str = getattr(sys, 'platlibdir', 'lib')
_USE_SYSCONFIG_DEFAULT = sys.version_info >= (3, 10)
@ -55,7 +62,7 @@ def _should_use_sysconfig() -> bool:
This is a function for testability, but should be constant during any one
run.
"""
return bool(getattr(sysconfig, "_PIP_USE_SYSCONFIG", _USE_SYSCONFIG_DEFAULT))
return bool(getattr(sysconfig, '_PIP_USE_SYSCONFIG', _USE_SYSCONFIG_DEFAULT))
_USE_SYSCONFIG = _should_use_sysconfig()
@ -76,20 +83,20 @@ def _looks_like_bpo_44860() -> bool:
from distutils.command.install import INSTALL_SCHEMES # type: ignore
try:
unix_user_platlib = INSTALL_SCHEMES["unix_user"]["platlib"]
unix_user_platlib = INSTALL_SCHEMES['unix_user']['platlib']
except KeyError:
return False
return unix_user_platlib == "$usersite"
return unix_user_platlib == '$usersite'
def _looks_like_red_hat_patched_platlib_purelib(scheme: Dict[str, str]) -> bool:
platlib = scheme["platlib"]
if "/$platlibdir/" in platlib:
platlib = platlib.replace("/$platlibdir/", f"/{_PLATLIBDIR}/")
if "/lib64/" not in platlib:
def _looks_like_red_hat_patched_platlib_purelib(scheme: dict[str, str]) -> bool:
platlib = scheme['platlib']
if '/$platlibdir/' in platlib:
platlib = platlib.replace('/$platlibdir/', f'/{_PLATLIBDIR}/')
if '/lib64/' not in platlib:
return False
unpatched = platlib.replace("/lib64/", "/lib/")
return unpatched.replace("$platbase/", "$base/") == scheme["purelib"]
unpatched = platlib.replace('/lib64/', '/lib/')
return unpatched.replace('$platbase/', '$base/') == scheme['purelib']
@functools.lru_cache(maxsize=None)
@ -101,9 +108,9 @@ def _looks_like_red_hat_lib() -> bool:
from distutils.command.install import INSTALL_SCHEMES # type: ignore
return all(
k in INSTALL_SCHEMES
and _looks_like_red_hat_patched_platlib_purelib(INSTALL_SCHEMES[k])
for k in ("unix_prefix", "unix_home")
k in INSTALL_SCHEMES and
_looks_like_red_hat_patched_platlib_purelib(INSTALL_SCHEMES[k])
for k in ('unix_prefix', 'unix_home')
)
@ -112,7 +119,7 @@ def _looks_like_debian_scheme() -> bool:
"""Debian adds two additional schemes."""
from distutils.command.install import INSTALL_SCHEMES # type: ignore
return "deb_system" in INSTALL_SCHEMES and "unix_local" in INSTALL_SCHEMES
return 'deb_system' in INSTALL_SCHEMES and 'unix_local' in INSTALL_SCHEMES
@functools.lru_cache(maxsize=None)
@ -130,8 +137,8 @@ def _looks_like_red_hat_scheme() -> bool:
cmd: Any = install(Distribution())
cmd.finalize_options()
return (
cmd.exec_prefix == f"{os.path.normpath(sys.exec_prefix)}/local"
and cmd.prefix == f"{os.path.normpath(sys.prefix)}/local"
cmd.exec_prefix == f'{os.path.normpath(sys.exec_prefix)}/local' and
cmd.prefix == f'{os.path.normpath(sys.prefix)}/local'
)
@ -145,10 +152,10 @@ def _looks_like_slackware_scheme() -> bool:
if user_site is None: # User-site not available.
return False
try:
paths = sysconfig.get_paths(scheme="posix_user", expand=False)
paths = sysconfig.get_paths(scheme='posix_user', expand=False)
except KeyError: # User-site not available.
return False
return "/lib64/" in paths["purelib"] and "/lib64/" not in user_site
return '/lib64/' in paths['purelib'] and '/lib64/' not in user_site
@functools.lru_cache(maxsize=None)
@ -162,16 +169,16 @@ def _looks_like_msys2_mingw_scheme() -> bool:
MSYS2 MINGW's patch uses lowercase ``"lib"`` instead of the usual uppercase,
and is missing the final ``"site-packages"``.
"""
paths = sysconfig.get_paths("nt", expand=False)
paths = sysconfig.get_paths('nt', expand=False)
return all(
"Lib" not in p and "lib" in p and not p.endswith("site-packages")
for p in (paths[key] for key in ("platlib", "purelib"))
'Lib' not in p and 'lib' in p and not p.endswith('site-packages')
for p in (paths[key] for key in ('platlib', 'purelib'))
)
def _fix_abiflags(parts: Tuple[str]) -> Iterator[str]:
ldversion = sysconfig.get_config_var("LDVERSION")
abiflags: str = getattr(sys, "abiflags", None)
def _fix_abiflags(parts: tuple[str]) -> Iterator[str]:
ldversion = sysconfig.get_config_var('LDVERSION')
abiflags: str = getattr(sys, 'abiflags', None)
# LDVERSION does not end with sys.abiflags. Just return the path unchanged.
if not ldversion or not abiflags or not ldversion.endswith(abiflags):
@ -187,11 +194,11 @@ def _fix_abiflags(parts: Tuple[str]) -> Iterator[str]:
@functools.lru_cache(maxsize=None)
def _warn_mismatched(old: pathlib.Path, new: pathlib.Path, *, key: str) -> None:
issue_url = "https://github.com/pypa/pip/issues/10151"
issue_url = 'https://github.com/pypa/pip/issues/10151'
message = (
"Value for %s does not match. Please report this to <%s>"
"\ndistutils: %s"
"\nsysconfig: %s"
'Value for %s does not match. Please report this to <%s>'
'\ndistutils: %s'
'\nsysconfig: %s'
)
logger.log(_MISMATCH_LEVEL, message, key, issue_url, old, new)
@ -207,28 +214,28 @@ def _warn_if_mismatch(old: pathlib.Path, new: pathlib.Path, *, key: str) -> bool
def _log_context(
*,
user: bool = False,
home: Optional[str] = None,
root: Optional[str] = None,
prefix: Optional[str] = None,
home: str | None = None,
root: str | None = None,
prefix: str | None = None,
) -> None:
parts = [
"Additional context:",
"user = %r",
"home = %r",
"root = %r",
"prefix = %r",
'Additional context:',
'user = %r',
'home = %r',
'root = %r',
'prefix = %r',
]
logger.log(_MISMATCH_LEVEL, "\n".join(parts), user, home, root, prefix)
logger.log(_MISMATCH_LEVEL, '\n'.join(parts), user, home, root, prefix)
def get_scheme(
dist_name: str,
user: bool = False,
home: Optional[str] = None,
root: Optional[str] = None,
home: str | None = None,
root: str | None = None,
isolated: bool = False,
prefix: Optional[str] = None,
prefix: str | None = None,
) -> Scheme:
new = _sysconfig.get_scheme(
dist_name,
@ -263,12 +270,12 @@ def get_scheme(
# 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.startswith("python")
and new_v.name.startswith("pypy")
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.startswith('python') and
new_v.name.startswith('pypy')
)
if skip_pypy_special_case:
continue
@ -277,18 +284,18 @@ def get_scheme(
# the ``include`` value, but distutils's ``headers`` does. We'll let
# CPython decide whether this is a bug or feature. See bpo-43948.
skip_osx_framework_user_special_case = (
user
and is_osx_framework()
and k == "headers"
and old_v.parent.parent == new_v.parent
and old_v.parent.name.startswith("python")
user and
is_osx_framework() and
k == 'headers' and
old_v.parent.parent == new_v.parent and
old_v.parent.name.startswith('python')
)
if skip_osx_framework_user_special_case:
continue
# On Red Hat and derived Linux distributions, distutils is patched to
# use "lib64" instead of "lib" for platlib.
if k == "platlib" and _looks_like_red_hat_lib():
if k == 'platlib' and _looks_like_red_hat_lib():
continue
# On Python 3.9+, sysconfig's posix_user scheme sets platlib against
@ -296,12 +303,12 @@ def get_scheme(
# using the same $usersite for both platlib and purelib. This creates a
# mismatch when sys.platlibdir is not "lib".
skip_bpo_44860 = (
user
and k == "platlib"
and not WINDOWS
and sys.version_info >= (3, 9)
and _PLATLIBDIR != "lib"
and _looks_like_bpo_44860()
user and
k == 'platlib' and
not WINDOWS and
sys.version_info >= (3, 9) and
_PLATLIBDIR != 'lib' and
_looks_like_bpo_44860()
)
if skip_bpo_44860:
continue
@ -309,10 +316,10 @@ def get_scheme(
# Slackware incorrectly patches posix_user to use lib64 instead of lib,
# but not usersite to match the location.
skip_slackware_user_scheme = (
user
and k in ("platlib", "purelib")
and not WINDOWS
and _looks_like_slackware_scheme()
user and
k in ('platlib', 'purelib') and
not WINDOWS and
_looks_like_slackware_scheme()
)
if skip_slackware_user_scheme:
continue
@ -321,12 +328,12 @@ def get_scheme(
# /usr/local instead of /usr. Debian also places lib in dist-packages
# instead of site-packages, but the /usr/local check should cover it.
skip_linux_system_special_case = (
not (user or home or prefix or running_under_virtualenv())
and old_v.parts[1:3] == ("usr", "local")
and len(new_v.parts) > 1
and new_v.parts[1] == "usr"
and (len(new_v.parts) < 3 or new_v.parts[2] != "local")
and (_looks_like_red_hat_scheme() or _looks_like_debian_scheme())
not (user or home or prefix or running_under_virtualenv()) and
old_v.parts[1:3] == ('usr', 'local') and
len(new_v.parts) > 1 and
new_v.parts[1] == 'usr' and
(len(new_v.parts) < 3 or new_v.parts[2] != 'local') and
(_looks_like_red_hat_scheme() or _looks_like_debian_scheme())
)
if skip_linux_system_special_case:
continue
@ -334,10 +341,10 @@ def get_scheme(
# On Python 3.7 and earlier, sysconfig does not include sys.abiflags in
# the "pythonX.Y" part of the path, but distutils does.
skip_sysconfig_abiflag_bug = (
sys.version_info < (3, 8)
and not WINDOWS
and k in ("headers", "platlib", "purelib")
and tuple(_fix_abiflags(old_v.parts)) == new_v.parts
sys.version_info < (3, 8) and
not WINDOWS and
k in ('headers', 'platlib', 'purelib') and
tuple(_fix_abiflags(old_v.parts)) == new_v.parts
)
if skip_sysconfig_abiflag_bug:
continue
@ -345,7 +352,7 @@ def get_scheme(
# MSYS2 MINGW's sysconfig patch does not include the "site-packages"
# part of the path. This is incorrect and will be fixed in MSYS.
skip_msys2_mingw_bug = (
WINDOWS and k in ("platlib", "purelib") and _looks_like_msys2_mingw_scheme()
WINDOWS and k in ('platlib', 'purelib') and _looks_like_msys2_mingw_scheme()
)
if skip_msys2_mingw_bug:
continue
@ -355,14 +362,14 @@ def get_scheme(
# triggers special logic in sysconfig that's not present in distutils.
# https://github.com/python/cpython/blob/8c21941ddaf/Lib/sysconfig.py#L178-L194
skip_cpython_build = (
sysconfig.is_python_build(check_home=True)
and not WINDOWS
and k in ("headers", "include", "platinclude")
sysconfig.is_python_build(check_home=True) and
not WINDOWS and
k in ('headers', 'include', 'platinclude')
)
if skip_cpython_build:
continue
warning_contexts.append((old_v, new_v, f"scheme.{k}"))
warning_contexts.append((old_v, new_v, f'scheme.{k}'))
if not warning_contexts:
return old
@ -382,10 +389,10 @@ def get_scheme(
if any(default_old[k] != getattr(old, k) for k in SCHEME_KEYS):
deprecated(
reason=(
"Configuring installation scheme with distutils config files "
"is deprecated and will no longer work in the near future. If you "
"are using a Homebrew or Linuxbrew Python, please see discussion "
"at https://github.com/Homebrew/homebrew-core/issues/76621"
'Configuring installation scheme with distutils config files '
'is deprecated and will no longer work in the near future. If you '
'are using a Homebrew or Linuxbrew Python, please see discussion '
'at https://github.com/Homebrew/homebrew-core/issues/76621'
),
replacement=None,
gone_in=None,
@ -406,13 +413,13 @@ def get_bin_prefix() -> str:
return new
old = _distutils.get_bin_prefix()
if _warn_if_mismatch(pathlib.Path(old), pathlib.Path(new), key="bin_prefix"):
if _warn_if_mismatch(pathlib.Path(old), pathlib.Path(new), key='bin_prefix'):
_log_context()
return old
def get_bin_user() -> str:
return _sysconfig.get_scheme("", user=True).scripts
return _sysconfig.get_scheme('', user=True).scripts
def _looks_like_deb_system_dist_packages(value: str) -> bool:
@ -427,7 +434,7 @@ def _looks_like_deb_system_dist_packages(value: str) -> bool:
"""
if not _looks_like_debian_scheme():
return False
if value == "/usr/lib/python3/dist-packages":
if value == '/usr/lib/python3/dist-packages':
return True
return False
@ -441,7 +448,7 @@ def get_purelib() -> str:
old = _distutils.get_purelib()
if _looks_like_deb_system_dist_packages(old):
return old
if _warn_if_mismatch(pathlib.Path(old), pathlib.Path(new), key="purelib"):
if _warn_if_mismatch(pathlib.Path(old), pathlib.Path(new), key='purelib'):
_log_context()
return old
@ -455,12 +462,12 @@ def get_platlib() -> str:
old = _distutils.get_platlib()
if _looks_like_deb_system_dist_packages(old):
return old
if _warn_if_mismatch(pathlib.Path(old), pathlib.Path(new), key="platlib"):
if _warn_if_mismatch(pathlib.Path(old), pathlib.Path(new), key='platlib'):
_log_context()
return old
def _deduplicated(v1: str, v2: str) -> List[str]:
def _deduplicated(v1: str, v2: str) -> list[str]:
"""Deduplicate values from a list."""
if v1 == v2:
return [v1]
@ -469,12 +476,12 @@ def _deduplicated(v1: str, v2: str) -> List[str]:
def _looks_like_apple_library(path: str) -> bool:
"""Apple patches sysconfig to *always* look under */Library/Python*."""
if sys.platform[:6] != "darwin":
if sys.platform[:6] != 'darwin':
return False
return path == f"/Library/Python/{get_major_minor_version()}/site-packages"
return path == f'/Library/Python/{get_major_minor_version()}/site-packages'
def get_prefixed_libs(prefix: str) -> List[str]:
def get_prefixed_libs(prefix: str) -> list[str]:
"""Return the lib locations under ``prefix``."""
new_pure, new_plat = _sysconfig.get_prefixed_libs(prefix)
if _USE_SYSCONFIG:
@ -493,9 +500,9 @@ def get_prefixed_libs(prefix: str) -> List[str]:
reason=(
"Python distributed by Apple's Command Line Tools incorrectly "
"patches sysconfig to always point to '/Library/Python'. This "
"will cause build isolation to operate incorrectly on Python "
"3.10 or later. Please help report this to Apple so they can "
"fix this. https://developer.apple.com/bug-reporting/"
'will cause build isolation to operate incorrectly on Python '
'3.10 or later. Please help report this to Apple so they can '
'fix this. https://developer.apple.com/bug-reporting/'
),
replacement=None,
gone_in=None,
@ -506,12 +513,12 @@ def get_prefixed_libs(prefix: str) -> List[str]:
_warn_if_mismatch(
pathlib.Path(old_pure),
pathlib.Path(new_pure),
key="prefixed-purelib",
key='prefixed-purelib',
),
_warn_if_mismatch(
pathlib.Path(old_plat),
pathlib.Path(new_plat),
key="prefixed-platlib",
key='prefixed-platlib',
),
]
if any(warned):

View file

@ -1,17 +1,22 @@
"""Locations where we look for configs, install stuff, etc"""
# The following comment should be removed at some point in the future.
# mypy: strict-optional=False
from __future__ import annotations
import logging
import os
import sys
from distutils.cmd import Command as DistutilsCommand
from distutils.command.install import SCHEME_KEYS
from distutils.command.install import install as distutils_install_command
from distutils.sysconfig import get_python_lib
from typing import Dict, List, Optional, Tuple, Union, cast
from typing import cast
from typing import Dict
from typing import List
from typing import Optional
from typing import Tuple
from typing import Union
from distutils.cmd import Command as DistutilsCommand
from distutils.command.install import install as distutils_install_command
from distutils.command.install import SCHEME_KEYS
from distutils.sysconfig import get_python_lib
from pip._internal.models.scheme import Scheme
from pip._internal.utils.compat import WINDOWS
from pip._internal.utils.virtualenv import running_under_virtualenv
@ -30,15 +35,15 @@ def distutils_scheme(
prefix: str = None,
*,
ignore_config_files: bool = False,
) -> Dict[str, str]:
) -> dict[str, str]:
"""
Return a distutils install scheme
"""
from distutils.dist import Distribution
dist_args: Dict[str, Union[str, List[str]]] = {"name": dist_name}
dist_args: dict[str, str | list[str]] = {'name': dist_name}
if isolated:
dist_args["script_args"] = ["--no-user-cfg"]
dist_args['script_args'] = ['--no-user-cfg']
d = Distribution(dist_args)
if not ignore_config_files:
@ -48,21 +53,21 @@ def distutils_scheme(
# Typeshed does not include find_config_files() for some reason.
paths = d.find_config_files() # type: ignore
logger.warning(
"Ignore distutils configs in %s due to encoding errors.",
", ".join(os.path.basename(p) for p in paths),
'Ignore distutils configs in %s due to encoding errors.',
', '.join(os.path.basename(p) for p in paths),
)
obj: Optional[DistutilsCommand] = None
obj = d.get_command_obj("install", create=True)
obj: DistutilsCommand | None = None
obj = d.get_command_obj('install', create=True)
assert obj is not None
i = cast(distutils_install_command, obj)
# NOTE: setting user or home has the side-effect of creating the home dir
# or user base for installations during finalize_options()
# ideally, we'd prefer a scheme class that has no side-effects.
assert not (user and prefix), f"user={user} prefix={prefix}"
assert not (home and prefix), f"home={home} prefix={prefix}"
assert not (user and prefix), f'user={user} prefix={prefix}'
assert not (home and prefix), f'home={home} prefix={prefix}'
i.user = user or i.user
if user or home:
i.prefix = ""
i.prefix = ''
i.prefix = prefix or i.prefix
i.home = home or i.home
i.root = root or i.root
@ -70,14 +75,14 @@ def distutils_scheme(
scheme = {}
for key in SCHEME_KEYS:
scheme[key] = getattr(i, "install_" + key)
scheme[key] = getattr(i, 'install_' + key)
# install_lib specified in setup.cfg should install *everything*
# into there (i.e. it takes precedence over both purelib and
# platlib). Note, i.install_lib is *always* set after
# finalize_options(); we only want to override here if the user
# has explicitly requested it hence going back to the config
if "install_lib" in d.get_option_dict("install"):
if 'install_lib' in d.get_option_dict('install'):
scheme.update(dict(purelib=i.install_lib, platlib=i.install_lib))
if running_under_virtualenv():
@ -87,17 +92,17 @@ def distutils_scheme(
prefix = i.install_userbase # type: ignore
else:
prefix = i.prefix
scheme["headers"] = os.path.join(
scheme['headers'] = os.path.join(
prefix,
"include",
"site",
f"python{get_major_minor_version()}",
'include',
'site',
f'python{get_major_minor_version()}',
dist_name,
)
if root is not None:
path_no_drive = os.path.splitdrive(os.path.abspath(scheme["headers"]))[1]
scheme["headers"] = os.path.join(root, path_no_drive[1:])
path_no_drive = os.path.splitdrive(os.path.abspath(scheme['headers']))[1]
scheme['headers'] = os.path.join(root, path_no_drive[1:])
return scheme
@ -105,10 +110,10 @@ def distutils_scheme(
def get_scheme(
dist_name: str,
user: bool = False,
home: Optional[str] = None,
root: Optional[str] = None,
home: str | None = None,
root: str | None = None,
isolated: bool = False,
prefix: Optional[str] = None,
prefix: str | None = None,
) -> Scheme:
"""
Get the "scheme" corresponding to the input parameters. The distutils
@ -129,11 +134,11 @@ def get_scheme(
"""
scheme = distutils_scheme(dist_name, user, home, root, isolated, prefix)
return Scheme(
platlib=scheme["platlib"],
purelib=scheme["purelib"],
headers=scheme["headers"],
scripts=scheme["scripts"],
data=scheme["data"],
platlib=scheme['platlib'],
purelib=scheme['purelib'],
headers=scheme['headers'],
scripts=scheme['scripts'],
data=scheme['data'],
)
@ -142,16 +147,16 @@ def get_bin_prefix() -> str:
# so we need to call normpath to eliminate them.
prefix = os.path.normpath(sys.prefix)
if WINDOWS:
bin_py = os.path.join(prefix, "Scripts")
bin_py = os.path.join(prefix, 'Scripts')
# buildout uses 'bin' on Windows too?
if not os.path.exists(bin_py):
bin_py = os.path.join(prefix, "bin")
bin_py = os.path.join(prefix, 'bin')
return bin_py
# Forcing to use /usr/local/bin for standard macOS framework installs
# Also log to ~/Library/Logs/ for use with the Console.app log viewer
if sys.platform[:6] == "darwin" and prefix[:16] == "/System/Library/":
return "/usr/local/bin"
return os.path.join(prefix, "bin")
if sys.platform[:6] == 'darwin' and prefix[:16] == '/System/Library/':
return '/usr/local/bin'
return os.path.join(prefix, 'bin')
def get_purelib() -> str:
@ -162,7 +167,7 @@ def get_platlib() -> str:
return get_python_lib(plat_specific=True)
def get_prefixed_libs(prefix: str) -> Tuple[str, str]:
def get_prefixed_libs(prefix: str) -> tuple[str, str]:
return (
get_python_lib(plat_specific=False, prefix=prefix),
get_python_lib(plat_specific=True, prefix=prefix),

View file

@ -1,15 +1,20 @@
import distutils.util # FIXME: For change_root.
from __future__ import annotations
import logging
import os
import sys
import sysconfig
import typing
from pip._internal.exceptions import InvalidSchemeCombination, UserInstallationInvalid
from pip._internal.models.scheme import SCHEME_KEYS, Scheme
import distutils.util # FIXME: For change_root.
from pip._internal.exceptions import InvalidSchemeCombination
from pip._internal.exceptions import UserInstallationInvalid
from pip._internal.models.scheme import Scheme
from pip._internal.models.scheme import SCHEME_KEYS
from pip._internal.utils.virtualenv import running_under_virtualenv
from .base import get_major_minor_version, is_osx_framework
from .base import get_major_minor_version
from .base import is_osx_framework
logger = logging.getLogger(__name__)
@ -24,7 +29,7 @@ logger = logging.getLogger(__name__)
_AVAILABLE_SCHEMES = set(sysconfig.get_scheme_names())
_PREFERRED_SCHEME_API = getattr(sysconfig, "get_preferred_scheme", None)
_PREFERRED_SCHEME_API = getattr(sysconfig, 'get_preferred_scheme', None)
def _should_use_osx_framework_prefix() -> bool:
@ -47,9 +52,9 @@ def _should_use_osx_framework_prefix() -> bool:
or our own, and we deal with this special case in ``get_scheme()`` instead.
"""
return (
"osx_framework_library" in _AVAILABLE_SCHEMES
and not running_under_virtualenv()
and is_osx_framework()
'osx_framework_library' in _AVAILABLE_SCHEMES and
not running_under_virtualenv() and
is_osx_framework()
)
@ -68,67 +73,67 @@ def _infer_prefix() -> str:
If none of the above works, fall back to ``posix_prefix``.
"""
if _PREFERRED_SCHEME_API:
return _PREFERRED_SCHEME_API("prefix")
return _PREFERRED_SCHEME_API('prefix')
if _should_use_osx_framework_prefix():
return "osx_framework_library"
implementation_suffixed = f"{sys.implementation.name}_{os.name}"
return 'osx_framework_library'
implementation_suffixed = f'{sys.implementation.name}_{os.name}'
if implementation_suffixed in _AVAILABLE_SCHEMES:
return implementation_suffixed
if sys.implementation.name in _AVAILABLE_SCHEMES:
return sys.implementation.name
suffixed = f"{os.name}_prefix"
suffixed = f'{os.name}_prefix'
if suffixed in _AVAILABLE_SCHEMES:
return suffixed
if os.name in _AVAILABLE_SCHEMES: # On Windows, prefx is just called "nt".
return os.name
return "posix_prefix"
return 'posix_prefix'
def _infer_user() -> str:
"""Try to find a user scheme for the current platform."""
if _PREFERRED_SCHEME_API:
return _PREFERRED_SCHEME_API("user")
return _PREFERRED_SCHEME_API('user')
if is_osx_framework() and not running_under_virtualenv():
suffixed = "osx_framework_user"
suffixed = 'osx_framework_user'
else:
suffixed = f"{os.name}_user"
suffixed = f'{os.name}_user'
if suffixed in _AVAILABLE_SCHEMES:
return suffixed
if "posix_user" not in _AVAILABLE_SCHEMES: # User scheme unavailable.
if 'posix_user' not in _AVAILABLE_SCHEMES: # User scheme unavailable.
raise UserInstallationInvalid()
return "posix_user"
return 'posix_user'
def _infer_home() -> str:
"""Try to find a home for the current platform."""
if _PREFERRED_SCHEME_API:
return _PREFERRED_SCHEME_API("home")
suffixed = f"{os.name}_home"
return _PREFERRED_SCHEME_API('home')
suffixed = f'{os.name}_home'
if suffixed in _AVAILABLE_SCHEMES:
return suffixed
return "posix_home"
return 'posix_home'
# Update these keys if the user sets a custom home.
_HOME_KEYS = [
"installed_base",
"base",
"installed_platbase",
"platbase",
"prefix",
"exec_prefix",
'installed_base',
'base',
'installed_platbase',
'platbase',
'prefix',
'exec_prefix',
]
if sysconfig.get_config_var("userbase") is not None:
_HOME_KEYS.append("userbase")
if sysconfig.get_config_var('userbase') is not None:
_HOME_KEYS.append('userbase')
def get_scheme(
dist_name: str,
user: bool = False,
home: typing.Optional[str] = None,
root: typing.Optional[str] = None,
home: str | None = None,
root: str | None = None,
isolated: bool = False,
prefix: typing.Optional[str] = None,
prefix: str | None = None,
) -> Scheme:
"""
Get the "scheme" corresponding to the input parameters.
@ -144,9 +149,9 @@ def get_scheme(
base directory for the same
"""
if user and prefix:
raise InvalidSchemeCombination("--user", "--prefix")
raise InvalidSchemeCombination('--user', '--prefix')
if home and prefix:
raise InvalidSchemeCombination("--home", "--prefix")
raise InvalidSchemeCombination('--home', '--prefix')
if home is not None:
scheme_name = _infer_home()
@ -158,8 +163,8 @@ def get_scheme(
# Special case: When installing into a custom prefix, use posix_prefix
# instead of osx_framework_library. See _should_use_osx_framework_prefix()
# docstring for details.
if prefix is not None and scheme_name == "osx_framework_library":
scheme_name = "posix_prefix"
if prefix is not None and scheme_name == 'osx_framework_library':
scheme_name = 'posix_prefix'
if home is not None:
variables = {k: home for k in _HOME_KEYS}
@ -177,20 +182,20 @@ def get_scheme(
# pip's historical header path logic (see point 1) did not do this.
if running_under_virtualenv():
if user:
base = variables.get("userbase", sys.prefix)
base = variables.get('userbase', sys.prefix)
else:
base = variables.get("base", sys.prefix)
python_xy = f"python{get_major_minor_version()}"
paths["include"] = os.path.join(base, "include", "site", python_xy)
base = variables.get('base', sys.prefix)
python_xy = f'python{get_major_minor_version()}'
paths['include'] = os.path.join(base, 'include', 'site', python_xy)
elif not dist_name:
dist_name = "UNKNOWN"
dist_name = 'UNKNOWN'
scheme = Scheme(
platlib=paths["platlib"],
purelib=paths["purelib"],
headers=os.path.join(paths["include"], dist_name),
scripts=paths["scripts"],
data=paths["data"],
platlib=paths['platlib'],
purelib=paths['purelib'],
headers=os.path.join(paths['include'], dist_name),
scripts=paths['scripts'],
data=paths['data'],
)
if root is not None:
for key in SCHEME_KEYS:
@ -201,19 +206,19 @@ def get_scheme(
def get_bin_prefix() -> str:
# Forcing to use /usr/local/bin for standard macOS framework installs.
if sys.platform[:6] == "darwin" and sys.prefix[:16] == "/System/Library/":
return "/usr/local/bin"
return sysconfig.get_paths()["scripts"]
if sys.platform[:6] == 'darwin' and sys.prefix[:16] == '/System/Library/':
return '/usr/local/bin'
return sysconfig.get_paths()['scripts']
def get_purelib() -> str:
return sysconfig.get_paths()["purelib"]
return sysconfig.get_paths()['purelib']
def get_platlib() -> str:
return sysconfig.get_paths()["platlib"]
return sysconfig.get_paths()['platlib']
def get_prefixed_libs(prefix: str) -> typing.Tuple[str, str]:
paths = sysconfig.get_paths(vars={"base": prefix, "platbase": prefix})
return (paths["purelib"], paths["platlib"])
def get_prefixed_libs(prefix: str) -> tuple[str, str]:
paths = sysconfig.get_paths(vars={'base': prefix, 'platbase': prefix})
return (paths['purelib'], paths['platlib'])

View file

@ -1,3 +1,5 @@
from __future__ import annotations
import functools
import os
import site
@ -9,10 +11,10 @@ from pip._internal.utils import appdirs
from pip._internal.utils.virtualenv import running_under_virtualenv
# Application Directories
USER_CACHE_DIR = appdirs.user_cache_dir("pip")
USER_CACHE_DIR = appdirs.user_cache_dir('pip')
# FIXME doesn't account for venv linked to global site-packages
site_packages: typing.Optional[str] = sysconfig.get_path("purelib")
site_packages: str | None = sysconfig.get_path('purelib')
def get_major_minor_version() -> str:
@ -20,19 +22,19 @@ def get_major_minor_version() -> str:
Return the major-minor version of the current Python as a string, e.g.
"3.7" or "3.10".
"""
return "{}.{}".format(*sys.version_info)
return '{}.{}'.format(*sys.version_info)
def get_src_prefix() -> str:
if running_under_virtualenv():
src_prefix = os.path.join(sys.prefix, "src")
src_prefix = os.path.join(sys.prefix, 'src')
else:
# FIXME: keep src in cwd for now (it is not a temporary folder)
try:
src_prefix = os.path.join(os.getcwd(), "src")
src_prefix = os.path.join(os.getcwd(), 'src')
except OSError:
# In case the current working directory has been renamed or deleted
sys.exit("The folder you are executing pip from can no longer be found.")
sys.exit('The folder you are executing pip from can no longer be found.')
# under macOS + virtualenv sys.prefix is not properly resolved
# it is something like /path/to/python/bin/..
@ -42,11 +44,11 @@ def get_src_prefix() -> str:
try:
# Use getusersitepackages if this is present, as it ensures that the
# value is initialised properly.
user_site: typing.Optional[str] = site.getusersitepackages()
user_site: str | None = site.getusersitepackages()
except AttributeError:
user_site = site.USER_SITE
@functools.lru_cache(maxsize=None)
def is_osx_framework() -> bool:
return bool(sysconfig.get_config_var("PYTHONFRAMEWORK"))
return bool(sysconfig.get_config_var('PYTHONFRAMEWORK'))