Загрузить файлы в «venv/Lib/site-packages/pip/_internal»
This commit is contained in:
12
venv/Lib/site-packages/pip/_internal/main.py
Normal file
12
venv/Lib/site-packages/pip/_internal/main.py
Normal file
@@ -0,0 +1,12 @@
|
||||
from __future__ import annotations
|
||||
|
||||
|
||||
def main(args: list[str] | None = None) -> int:
|
||||
"""This is preserved for old console scripts that may still be referencing
|
||||
it.
|
||||
|
||||
For additional details, see https://github.com/pypa/pip/issues/7498.
|
||||
"""
|
||||
from pip._internal.utils.entrypoints import _wrapper
|
||||
|
||||
return _wrapper(args)
|
||||
123
venv/Lib/site-packages/pip/_internal/pyproject.py
Normal file
123
venv/Lib/site-packages/pip/_internal/pyproject.py
Normal file
@@ -0,0 +1,123 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from collections import namedtuple
|
||||
from typing import Any
|
||||
|
||||
from pip._vendor.packaging.requirements import InvalidRequirement
|
||||
|
||||
from pip._internal.exceptions import (
|
||||
InstallationError,
|
||||
InvalidPyProjectBuildRequires,
|
||||
MissingPyProjectBuildRequires,
|
||||
)
|
||||
from pip._internal.utils.compat import tomllib
|
||||
from pip._internal.utils.packaging import get_requirement
|
||||
|
||||
|
||||
def _is_list_of_str(obj: Any) -> bool:
|
||||
return isinstance(obj, list) and all(isinstance(item, str) for item in obj)
|
||||
|
||||
|
||||
def make_pyproject_path(unpacked_source_directory: str) -> str:
|
||||
return os.path.join(unpacked_source_directory, "pyproject.toml")
|
||||
|
||||
|
||||
BuildSystemDetails = namedtuple(
|
||||
"BuildSystemDetails", ["requires", "backend", "check", "backend_path"]
|
||||
)
|
||||
|
||||
|
||||
def load_pyproject_toml(
|
||||
pyproject_toml: str, setup_py: str, req_name: str
|
||||
) -> BuildSystemDetails:
|
||||
"""Load the pyproject.toml file.
|
||||
|
||||
Parameters:
|
||||
pyproject_toml - Location of the project's pyproject.toml file
|
||||
setup_py - Location of the project's setup.py file
|
||||
req_name - The name of the requirement we're processing (for
|
||||
error reporting)
|
||||
|
||||
Returns:
|
||||
None if we should use the legacy code path, otherwise a tuple
|
||||
(
|
||||
requirements from pyproject.toml,
|
||||
name of PEP 517 backend,
|
||||
requirements we should check are installed after setting
|
||||
up the build environment
|
||||
directory paths to import the backend from (backend-path),
|
||||
relative to the project root.
|
||||
)
|
||||
"""
|
||||
has_pyproject = os.path.isfile(pyproject_toml)
|
||||
has_setup = os.path.isfile(setup_py)
|
||||
|
||||
if not has_pyproject and not has_setup:
|
||||
raise InstallationError(
|
||||
f"{req_name} does not appear to be a Python project: "
|
||||
f"neither 'setup.py' nor 'pyproject.toml' found."
|
||||
)
|
||||
|
||||
if has_pyproject:
|
||||
with open(pyproject_toml, encoding="utf-8") as f:
|
||||
pp_toml = tomllib.loads(f.read())
|
||||
build_system = pp_toml.get("build-system")
|
||||
else:
|
||||
build_system = None
|
||||
|
||||
if build_system is None:
|
||||
# In the absence of any explicit backend specification, we
|
||||
# assume the setuptools backend that most closely emulates the
|
||||
# traditional direct setup.py execution, and require wheel and
|
||||
# a version of setuptools that supports that backend.
|
||||
|
||||
build_system = {
|
||||
"requires": ["setuptools>=40.8.0"],
|
||||
"build-backend": "setuptools.build_meta:__legacy__",
|
||||
}
|
||||
|
||||
# Ensure that the build-system section in pyproject.toml conforms
|
||||
# to PEP 518.
|
||||
|
||||
# Specifying the build-system table but not the requires key is invalid
|
||||
if "requires" not in build_system:
|
||||
raise MissingPyProjectBuildRequires(package=req_name)
|
||||
|
||||
# Error out if requires is not a list of strings
|
||||
requires = build_system["requires"]
|
||||
if not _is_list_of_str(requires):
|
||||
raise InvalidPyProjectBuildRequires(
|
||||
package=req_name,
|
||||
reason="It is not a list of strings.",
|
||||
)
|
||||
|
||||
# Each requirement must be valid as per PEP 508
|
||||
for requirement in requires:
|
||||
try:
|
||||
get_requirement(requirement)
|
||||
except InvalidRequirement as error:
|
||||
raise InvalidPyProjectBuildRequires(
|
||||
package=req_name,
|
||||
reason=f"It contains an invalid requirement: {requirement!r}",
|
||||
) from error
|
||||
|
||||
backend = build_system.get("build-backend")
|
||||
backend_path = build_system.get("backend-path", [])
|
||||
check: list[str] = []
|
||||
if backend is None:
|
||||
# If the user didn't specify a backend, we assume they want to use
|
||||
# the setuptools backend. But we can't be sure they have included
|
||||
# a version of setuptools which supplies the backend. So we
|
||||
# make a note to check that this requirement is present once
|
||||
# we have set up the environment.
|
||||
# This is quite a lot of work to check for a very specific case. But
|
||||
# the problem is, that case is potentially quite common - projects that
|
||||
# adopted PEP 518 early for the ability to specify requirements to
|
||||
# execute setup.py, but never considered needing to mention the build
|
||||
# tools themselves. The original PEP 518 code had a similar check (but
|
||||
# implemented in a different way).
|
||||
backend = "setuptools.build_meta:__legacy__"
|
||||
check = ["setuptools>=40.8.0"]
|
||||
|
||||
return BuildSystemDetails(requires, backend, check, backend_path)
|
||||
255
venv/Lib/site-packages/pip/_internal/self_outdated_check.py
Normal file
255
venv/Lib/site-packages/pip/_internal/self_outdated_check.py
Normal file
@@ -0,0 +1,255 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import datetime
|
||||
import functools
|
||||
import hashlib
|
||||
import json
|
||||
import logging
|
||||
import optparse
|
||||
import os.path
|
||||
import sys
|
||||
from dataclasses import dataclass
|
||||
from typing import Callable
|
||||
|
||||
from pip._vendor.packaging.version import Version
|
||||
from pip._vendor.packaging.version import parse as parse_version
|
||||
from pip._vendor.rich.console import Group
|
||||
from pip._vendor.rich.markup import escape
|
||||
from pip._vendor.rich.text import Text
|
||||
|
||||
from pip._internal.index.collector import LinkCollector
|
||||
from pip._internal.index.package_finder import PackageFinder
|
||||
from pip._internal.metadata import get_default_environment
|
||||
from pip._internal.models.release_control import ReleaseControl
|
||||
from pip._internal.models.selection_prefs import SelectionPreferences
|
||||
from pip._internal.network.session import PipSession
|
||||
from pip._internal.utils.compat import WINDOWS
|
||||
from pip._internal.utils.datetime import parse_iso_datetime
|
||||
from pip._internal.utils.entrypoints import (
|
||||
get_best_invocation_for_this_pip,
|
||||
get_best_invocation_for_this_python,
|
||||
)
|
||||
from pip._internal.utils.filesystem import (
|
||||
adjacent_tmp_file,
|
||||
check_path_owner,
|
||||
copy_directory_permissions,
|
||||
replace,
|
||||
)
|
||||
from pip._internal.utils.misc import (
|
||||
ExternallyManagedEnvironment,
|
||||
check_externally_managed,
|
||||
ensure_dir,
|
||||
)
|
||||
|
||||
_WEEK = datetime.timedelta(days=7)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _get_statefile_name(key: str) -> str:
|
||||
key_bytes = key.encode()
|
||||
name = hashlib.sha224(key_bytes).hexdigest()
|
||||
return name
|
||||
|
||||
|
||||
class SelfCheckState:
|
||||
def __init__(self, cache_dir: str) -> None:
|
||||
self._state: dict[str, str] = {}
|
||||
self._statefile_path = None
|
||||
|
||||
# Try to load the existing state
|
||||
if cache_dir:
|
||||
self._statefile_path = os.path.join(
|
||||
cache_dir, "selfcheck", _get_statefile_name(self.key)
|
||||
)
|
||||
try:
|
||||
with open(self._statefile_path, encoding="utf-8") as statefile:
|
||||
self._state = json.load(statefile)
|
||||
except (OSError, ValueError, KeyError):
|
||||
# Explicitly suppressing exceptions, since we don't want to
|
||||
# error out if the cache file is invalid.
|
||||
pass
|
||||
|
||||
@property
|
||||
def key(self) -> str:
|
||||
return sys.prefix
|
||||
|
||||
def get(self, current_time: datetime.datetime) -> str | None:
|
||||
"""Check if we have a not-outdated version loaded already."""
|
||||
if not self._state:
|
||||
return None
|
||||
|
||||
if "last_check" not in self._state:
|
||||
return None
|
||||
|
||||
if "pypi_version" not in self._state:
|
||||
return None
|
||||
|
||||
# Determine if we need to refresh the state
|
||||
last_check = parse_iso_datetime(self._state["last_check"])
|
||||
time_since_last_check = current_time - last_check
|
||||
if time_since_last_check > _WEEK:
|
||||
return None
|
||||
|
||||
return self._state["pypi_version"]
|
||||
|
||||
def set(self, pypi_version: str, current_time: datetime.datetime) -> None:
|
||||
# If we do not have a path to cache in, don't bother saving.
|
||||
if not self._statefile_path:
|
||||
return
|
||||
|
||||
statefile_directory = os.path.dirname(self._statefile_path)
|
||||
|
||||
# Check to make sure that we own the directory
|
||||
if not check_path_owner(statefile_directory):
|
||||
return
|
||||
|
||||
# Now that we've ensured the directory is owned by this user, we'll go
|
||||
# ahead and make sure that all our directories are created.
|
||||
ensure_dir(statefile_directory)
|
||||
|
||||
state = {
|
||||
# Include the key so it's easy to tell which pip wrote the
|
||||
# file.
|
||||
"key": self.key,
|
||||
"last_check": current_time.isoformat(),
|
||||
"pypi_version": pypi_version,
|
||||
}
|
||||
|
||||
text = json.dumps(state, sort_keys=True, separators=(",", ":"))
|
||||
|
||||
with adjacent_tmp_file(self._statefile_path) as f:
|
||||
f.write(text.encode())
|
||||
copy_directory_permissions(statefile_directory, f)
|
||||
|
||||
try:
|
||||
# Since we have a prefix-specific state file, we can just
|
||||
# overwrite whatever is there, no need to check.
|
||||
replace(f.name, self._statefile_path)
|
||||
except OSError:
|
||||
# Best effort.
|
||||
pass
|
||||
|
||||
|
||||
@dataclass
|
||||
class UpgradePrompt:
|
||||
old: str
|
||||
new: str
|
||||
|
||||
def __rich__(self) -> Group:
|
||||
if WINDOWS:
|
||||
pip_cmd = f"{get_best_invocation_for_this_python()} -m pip"
|
||||
else:
|
||||
pip_cmd = get_best_invocation_for_this_pip()
|
||||
|
||||
notice = "[bold][[reset][blue]notice[reset][bold]][reset]"
|
||||
return Group(
|
||||
Text(),
|
||||
Text.from_markup(
|
||||
f"{notice} A new release of pip is available: "
|
||||
f"[red]{self.old}[reset] -> [green]{self.new}[reset]"
|
||||
),
|
||||
Text.from_markup(
|
||||
f"{notice} To update, run: "
|
||||
f"[green]{escape(pip_cmd)} install --upgrade pip"
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
def was_installed_by_pip(pkg: str) -> bool:
|
||||
"""Checks whether pkg was installed by pip
|
||||
|
||||
This is used not to display the upgrade message when pip is in fact
|
||||
installed by system package manager, such as dnf on Fedora.
|
||||
"""
|
||||
dist = get_default_environment().get_distribution(pkg)
|
||||
return dist is not None and "pip" == dist.installer
|
||||
|
||||
|
||||
def _get_current_remote_pip_version(
|
||||
session: PipSession, options: optparse.Values
|
||||
) -> str | None:
|
||||
# Lets use PackageFinder to see what the latest pip version is
|
||||
link_collector = LinkCollector.create(
|
||||
session,
|
||||
options=options,
|
||||
suppress_no_index=True,
|
||||
)
|
||||
|
||||
# Pass allow_yanked=False so we don't suggest upgrading to a
|
||||
# yanked version.
|
||||
selection_prefs = SelectionPreferences(
|
||||
allow_yanked=False,
|
||||
release_control=ReleaseControl(only_final={"pip"}),
|
||||
)
|
||||
|
||||
finder = PackageFinder.create(
|
||||
link_collector=link_collector,
|
||||
selection_prefs=selection_prefs,
|
||||
)
|
||||
best_candidate = finder.find_best_candidate("pip").best_candidate
|
||||
if best_candidate is None:
|
||||
return None
|
||||
|
||||
return str(best_candidate.version)
|
||||
|
||||
|
||||
def _self_version_check_logic(
|
||||
*,
|
||||
state: SelfCheckState,
|
||||
current_time: datetime.datetime,
|
||||
local_version: Version,
|
||||
get_remote_version: Callable[[], str | None],
|
||||
) -> UpgradePrompt | None:
|
||||
remote_version_str = state.get(current_time)
|
||||
if remote_version_str is None:
|
||||
remote_version_str = get_remote_version()
|
||||
if remote_version_str is None:
|
||||
logger.debug("No remote pip version found")
|
||||
return None
|
||||
state.set(remote_version_str, current_time)
|
||||
|
||||
remote_version = parse_version(remote_version_str)
|
||||
logger.debug("Remote version of pip: %s", remote_version)
|
||||
logger.debug("Local version of pip: %s", local_version)
|
||||
|
||||
pip_installed_by_pip = was_installed_by_pip("pip")
|
||||
logger.debug("Was pip installed by pip? %s", pip_installed_by_pip)
|
||||
if not pip_installed_by_pip:
|
||||
return None # Only suggest upgrade if pip is installed by pip.
|
||||
|
||||
local_version_is_older = (
|
||||
local_version < remote_version
|
||||
and local_version.base_version != remote_version.base_version
|
||||
)
|
||||
if local_version_is_older:
|
||||
return UpgradePrompt(old=str(local_version), new=remote_version_str)
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def pip_self_version_check(session: PipSession, options: optparse.Values) -> None:
|
||||
"""Check for an update for pip.
|
||||
|
||||
Limit the frequency of checks to once per week. State is stored either in
|
||||
the active virtualenv or in the user's USER_CACHE_DIR keyed off the prefix
|
||||
of the pip script path.
|
||||
"""
|
||||
installed_dist = get_default_environment().get_distribution("pip")
|
||||
if not installed_dist:
|
||||
return
|
||||
try:
|
||||
check_externally_managed()
|
||||
except ExternallyManagedEnvironment:
|
||||
return
|
||||
|
||||
upgrade_prompt = _self_version_check_logic(
|
||||
state=SelfCheckState(cache_dir=options.cache_dir),
|
||||
current_time=datetime.datetime.now(datetime.timezone.utc),
|
||||
local_version=installed_dist.version,
|
||||
get_remote_version=functools.partial(
|
||||
_get_current_remote_pip_version, session, options
|
||||
),
|
||||
)
|
||||
if upgrade_prompt is not None:
|
||||
logger.warning("%s", upgrade_prompt, extra={"rich": True})
|
||||
261
venv/Lib/site-packages/pip/_internal/wheel_builder.py
Normal file
261
venv/Lib/site-packages/pip/_internal/wheel_builder.py
Normal file
@@ -0,0 +1,261 @@
|
||||
"""Orchestrator for building wheels from InstallRequirements."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import os.path
|
||||
import re
|
||||
from collections.abc import Iterable
|
||||
from tempfile import TemporaryDirectory
|
||||
|
||||
from pip._vendor.packaging.utils import canonicalize_name, canonicalize_version
|
||||
from pip._vendor.packaging.version import InvalidVersion, Version
|
||||
|
||||
from pip._internal.cache import WheelCache
|
||||
from pip._internal.exceptions import InvalidWheelFilename, UnsupportedWheel
|
||||
from pip._internal.metadata import FilesystemWheel, get_wheel_distribution
|
||||
from pip._internal.models.link import Link
|
||||
from pip._internal.models.wheel import Wheel
|
||||
from pip._internal.operations.build.wheel import build_wheel_pep517
|
||||
from pip._internal.operations.build.wheel_editable import build_wheel_editable
|
||||
from pip._internal.req.req_install import InstallRequirement
|
||||
from pip._internal.utils.logging import indent_log
|
||||
from pip._internal.utils.misc import ensure_dir, hash_file
|
||||
from pip._internal.utils.urls import path_to_url
|
||||
from pip._internal.vcs import vcs
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
_egg_info_re = re.compile(r"([a-z0-9_.]+)-([a-z0-9_.!+-]+)", re.IGNORECASE)
|
||||
|
||||
BuildResult = tuple[list[InstallRequirement], list[InstallRequirement]]
|
||||
|
||||
|
||||
def _contains_egg_info(s: str) -> bool:
|
||||
"""Determine whether the string looks like an egg_info.
|
||||
|
||||
:param s: The string to parse. E.g. foo-2.1
|
||||
"""
|
||||
return bool(_egg_info_re.search(s))
|
||||
|
||||
|
||||
def _should_cache(
|
||||
req: InstallRequirement,
|
||||
) -> bool | None:
|
||||
"""
|
||||
Return whether a built InstallRequirement can be stored in the persistent
|
||||
wheel cache, assuming the wheel cache is available.
|
||||
"""
|
||||
if req.editable or not req.source_dir:
|
||||
# never cache editable requirements
|
||||
return False
|
||||
|
||||
if req.link and req.link.is_vcs:
|
||||
# VCS checkout. Do not cache
|
||||
# unless it points to an immutable commit hash.
|
||||
assert not req.editable
|
||||
assert req.source_dir
|
||||
vcs_backend = vcs.get_backend_for_scheme(req.link.scheme)
|
||||
assert vcs_backend
|
||||
if vcs_backend.is_immutable_rev_checkout(req.link.url, req.source_dir):
|
||||
return True
|
||||
return False
|
||||
|
||||
assert req.link
|
||||
base, ext = req.link.splitext()
|
||||
if _contains_egg_info(base):
|
||||
return True
|
||||
|
||||
# Otherwise, do not cache.
|
||||
return False
|
||||
|
||||
|
||||
def _get_cache_dir(
|
||||
req: InstallRequirement,
|
||||
wheel_cache: WheelCache,
|
||||
) -> str:
|
||||
"""Return the persistent or temporary cache directory where the built
|
||||
wheel need to be stored.
|
||||
"""
|
||||
cache_available = bool(wheel_cache.cache_dir)
|
||||
assert req.link
|
||||
if cache_available and _should_cache(req):
|
||||
cache_dir = wheel_cache.get_path_for_link(req.link)
|
||||
else:
|
||||
cache_dir = wheel_cache.get_ephem_path_for_link(req.link)
|
||||
return cache_dir
|
||||
|
||||
|
||||
def _verify_one(req: InstallRequirement, wheel_path: str) -> None:
|
||||
canonical_name = canonicalize_name(req.name or "")
|
||||
w = Wheel(os.path.basename(wheel_path))
|
||||
if w.name != canonical_name:
|
||||
raise InvalidWheelFilename(
|
||||
f"Wheel has unexpected file name: expected {canonical_name!r}, "
|
||||
f"got {w.name!r}",
|
||||
)
|
||||
dist = get_wheel_distribution(FilesystemWheel(wheel_path), canonical_name)
|
||||
dist_verstr = str(dist.version)
|
||||
if canonicalize_version(dist_verstr) != canonicalize_version(w.version):
|
||||
raise InvalidWheelFilename(
|
||||
f"Wheel has unexpected file name: expected {dist_verstr!r}, "
|
||||
f"got {w.version!r}",
|
||||
)
|
||||
metadata_version_value = dist.metadata_version
|
||||
if metadata_version_value is None:
|
||||
raise UnsupportedWheel("Missing Metadata-Version")
|
||||
try:
|
||||
metadata_version = Version(metadata_version_value)
|
||||
except InvalidVersion:
|
||||
msg = f"Invalid Metadata-Version: {metadata_version_value}"
|
||||
raise UnsupportedWheel(msg)
|
||||
if metadata_version >= Version("1.2") and not isinstance(dist.version, Version):
|
||||
raise UnsupportedWheel(
|
||||
f"Metadata 1.2 mandates PEP 440 version, but {dist_verstr!r} is not"
|
||||
)
|
||||
|
||||
|
||||
def _build_one(
|
||||
req: InstallRequirement,
|
||||
output_dir: str,
|
||||
verify: bool,
|
||||
editable: bool,
|
||||
) -> str | None:
|
||||
"""Build one wheel.
|
||||
|
||||
:return: The filename of the built wheel, or None if the build failed.
|
||||
"""
|
||||
artifact = "editable" if editable else "wheel"
|
||||
try:
|
||||
ensure_dir(output_dir)
|
||||
except OSError as e:
|
||||
logger.warning(
|
||||
"Building %s for %s failed: %s",
|
||||
artifact,
|
||||
req.name,
|
||||
e,
|
||||
)
|
||||
return None
|
||||
|
||||
# Install build deps into temporary directory (PEP 518)
|
||||
with req.build_env:
|
||||
wheel_path = _build_one_inside_env(req, output_dir, editable)
|
||||
if wheel_path and verify:
|
||||
try:
|
||||
_verify_one(req, wheel_path)
|
||||
except (InvalidWheelFilename, UnsupportedWheel) as e:
|
||||
logger.warning("Built %s for %s is invalid: %s", artifact, req.name, e)
|
||||
return None
|
||||
return wheel_path
|
||||
|
||||
|
||||
def _build_one_inside_env(
|
||||
req: InstallRequirement,
|
||||
output_dir: str,
|
||||
editable: bool,
|
||||
) -> str | None:
|
||||
with TemporaryDirectory(dir=output_dir) as wheel_directory:
|
||||
assert req.name
|
||||
assert req.metadata_directory
|
||||
assert req.pep517_backend
|
||||
if editable:
|
||||
wheel_path = build_wheel_editable(
|
||||
name=req.name,
|
||||
backend=req.pep517_backend,
|
||||
metadata_directory=req.metadata_directory,
|
||||
wheel_directory=wheel_directory,
|
||||
)
|
||||
else:
|
||||
wheel_path = build_wheel_pep517(
|
||||
name=req.name,
|
||||
backend=req.pep517_backend,
|
||||
metadata_directory=req.metadata_directory,
|
||||
wheel_directory=wheel_directory,
|
||||
)
|
||||
|
||||
if wheel_path is not None:
|
||||
wheel_name = os.path.basename(wheel_path)
|
||||
dest_path = os.path.join(output_dir, wheel_name)
|
||||
try:
|
||||
wheel_hash, length = hash_file(wheel_path)
|
||||
# We can do a replace here because wheel_path is guaranteed to
|
||||
# be in the same filesystem as output_dir. This will perform an
|
||||
# atomic rename, which is necessary to avoid concurrency issues
|
||||
# when populating the cache.
|
||||
os.replace(wheel_path, dest_path)
|
||||
logger.info(
|
||||
"Created wheel for %s: filename=%s size=%d sha256=%s",
|
||||
req.name,
|
||||
wheel_name,
|
||||
length,
|
||||
wheel_hash.hexdigest(),
|
||||
)
|
||||
logger.info("Stored in directory: %s", output_dir)
|
||||
return dest_path
|
||||
except Exception as e:
|
||||
logger.warning(
|
||||
"Building wheel for %s failed: %s",
|
||||
req.name,
|
||||
e,
|
||||
)
|
||||
return None
|
||||
|
||||
|
||||
def build(
|
||||
requirements: Iterable[InstallRequirement],
|
||||
wheel_cache: WheelCache,
|
||||
verify: bool,
|
||||
) -> BuildResult:
|
||||
"""Build wheels.
|
||||
|
||||
:return: The list of InstallRequirement that succeeded to build and
|
||||
the list of InstallRequirement that failed to build.
|
||||
"""
|
||||
if not requirements:
|
||||
return [], []
|
||||
|
||||
# Build the wheels.
|
||||
logger.info(
|
||||
"Building wheels for collected packages: %s",
|
||||
", ".join(req.name for req in requirements), # type: ignore
|
||||
)
|
||||
|
||||
with indent_log():
|
||||
build_successes, build_failures = [], []
|
||||
for req in requirements:
|
||||
assert req.name
|
||||
cache_dir = _get_cache_dir(req, wheel_cache)
|
||||
wheel_file = _build_one(
|
||||
req,
|
||||
cache_dir,
|
||||
verify,
|
||||
req.editable and req.permit_editable_wheels,
|
||||
)
|
||||
if wheel_file:
|
||||
# Record the download origin in the cache
|
||||
if req.download_info is not None:
|
||||
# download_info is guaranteed to be set because when we build an
|
||||
# InstallRequirement it has been through the preparer before, but
|
||||
# let's be cautious.
|
||||
wheel_cache.record_download_origin(cache_dir, req.download_info)
|
||||
# Update the link for this.
|
||||
req.link = Link(path_to_url(wheel_file))
|
||||
req.local_file_path = req.link.file_path
|
||||
assert req.link.is_wheel
|
||||
build_successes.append(req)
|
||||
else:
|
||||
build_failures.append(req)
|
||||
|
||||
# notify success/failure
|
||||
if build_successes:
|
||||
logger.info(
|
||||
"Successfully built %s",
|
||||
" ".join([req.name for req in build_successes]), # type: ignore
|
||||
)
|
||||
if build_failures:
|
||||
logger.info(
|
||||
"Failed to build %s",
|
||||
" ".join([req.name for req in build_failures]), # type: ignore
|
||||
)
|
||||
# Return a list of requirements that failed to build
|
||||
return build_successes, build_failures
|
||||
Reference in New Issue
Block a user