Загрузить файлы в «venv/Lib/site-packages/pip/_internal/distributions»
This commit is contained in:
@@ -0,0 +1,21 @@
|
|||||||
|
from pip._internal.distributions.base import AbstractDistribution
|
||||||
|
from pip._internal.distributions.sdist import SourceDistribution
|
||||||
|
from pip._internal.distributions.wheel import WheelDistribution
|
||||||
|
from pip._internal.req.req_install import InstallRequirement
|
||||||
|
|
||||||
|
|
||||||
|
def make_distribution_for_install_requirement(
|
||||||
|
install_req: InstallRequirement,
|
||||||
|
) -> AbstractDistribution:
|
||||||
|
"""Returns a Distribution for the given InstallRequirement"""
|
||||||
|
# Editable requirements will always be source distributions. They use the
|
||||||
|
# legacy logic until we create a modern standard for them.
|
||||||
|
if install_req.editable:
|
||||||
|
return SourceDistribution(install_req)
|
||||||
|
|
||||||
|
# If it's a wheel, it's a WheelDistribution
|
||||||
|
if install_req.is_wheel:
|
||||||
|
return WheelDistribution(install_req)
|
||||||
|
|
||||||
|
# Otherwise, a SourceDistribution
|
||||||
|
return SourceDistribution(install_req)
|
||||||
55
venv/Lib/site-packages/pip/_internal/distributions/base.py
Normal file
55
venv/Lib/site-packages/pip/_internal/distributions/base.py
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import abc
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
from pip._internal.metadata.base import BaseDistribution
|
||||||
|
from pip._internal.req import InstallRequirement
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from pip._internal.build_env import BuildEnvironmentInstaller
|
||||||
|
|
||||||
|
|
||||||
|
class AbstractDistribution(metaclass=abc.ABCMeta):
|
||||||
|
"""A base class for handling installable artifacts.
|
||||||
|
|
||||||
|
The requirements for anything installable are as follows:
|
||||||
|
|
||||||
|
- we must be able to determine the requirement name
|
||||||
|
(or we can't correctly handle the non-upgrade case).
|
||||||
|
|
||||||
|
- for packages with setup requirements, we must also be able
|
||||||
|
to determine their requirements without installing additional
|
||||||
|
packages (for the same reason as run-time dependencies)
|
||||||
|
|
||||||
|
- we must be able to create a Distribution object exposing the
|
||||||
|
above metadata.
|
||||||
|
|
||||||
|
- if we need to do work in the build tracker, we must be able to generate a unique
|
||||||
|
string to identify the requirement in the build tracker.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, req: InstallRequirement) -> None:
|
||||||
|
super().__init__()
|
||||||
|
self.req = req
|
||||||
|
|
||||||
|
@abc.abstractproperty
|
||||||
|
def build_tracker_id(self) -> str | None:
|
||||||
|
"""A string that uniquely identifies this requirement to the build tracker.
|
||||||
|
|
||||||
|
If None, then this dist has no work to do in the build tracker, and
|
||||||
|
``.prepare_distribution_metadata()`` will not be called."""
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def get_metadata_distribution(self) -> BaseDistribution:
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def prepare_distribution_metadata(
|
||||||
|
self,
|
||||||
|
build_env_installer: BuildEnvironmentInstaller,
|
||||||
|
build_isolation: bool,
|
||||||
|
check_build_deps: bool,
|
||||||
|
) -> None:
|
||||||
|
raise NotImplementedError()
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
from pip._internal.distributions.base import AbstractDistribution
|
||||||
|
from pip._internal.metadata import BaseDistribution
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from pip._internal.build_env import BuildEnvironmentInstaller
|
||||||
|
|
||||||
|
|
||||||
|
class InstalledDistribution(AbstractDistribution):
|
||||||
|
"""Represents an installed package.
|
||||||
|
|
||||||
|
This does not need any preparation as the required information has already
|
||||||
|
been computed.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@property
|
||||||
|
def build_tracker_id(self) -> str | None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_metadata_distribution(self) -> BaseDistribution:
|
||||||
|
assert self.req.satisfied_by is not None, "not actually installed"
|
||||||
|
return self.req.satisfied_by
|
||||||
|
|
||||||
|
def prepare_distribution_metadata(
|
||||||
|
self,
|
||||||
|
build_env_installer: BuildEnvironmentInstaller,
|
||||||
|
build_isolation: bool,
|
||||||
|
check_build_deps: bool,
|
||||||
|
) -> None:
|
||||||
|
pass
|
||||||
164
venv/Lib/site-packages/pip/_internal/distributions/sdist.py
Normal file
164
venv/Lib/site-packages/pip/_internal/distributions/sdist.py
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import logging
|
||||||
|
from collections.abc import Iterable
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
from pip._internal.build_env import BuildEnvironment
|
||||||
|
from pip._internal.distributions.base import AbstractDistribution
|
||||||
|
from pip._internal.exceptions import InstallationError
|
||||||
|
from pip._internal.metadata import BaseDistribution
|
||||||
|
from pip._internal.utils.subprocess import runner_with_spinner_message
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from pip._internal.build_env import BuildEnvironmentInstaller
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class SourceDistribution(AbstractDistribution):
|
||||||
|
"""Represents a source distribution.
|
||||||
|
|
||||||
|
The preparation step for these needs metadata for the packages to be
|
||||||
|
generated.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@property
|
||||||
|
def build_tracker_id(self) -> str | None:
|
||||||
|
"""Identify this requirement uniquely by its link."""
|
||||||
|
assert self.req.link
|
||||||
|
return self.req.link.url_without_fragment
|
||||||
|
|
||||||
|
def get_metadata_distribution(self) -> BaseDistribution:
|
||||||
|
return self.req.get_dist()
|
||||||
|
|
||||||
|
def prepare_distribution_metadata(
|
||||||
|
self,
|
||||||
|
build_env_installer: BuildEnvironmentInstaller,
|
||||||
|
build_isolation: bool,
|
||||||
|
check_build_deps: bool,
|
||||||
|
) -> None:
|
||||||
|
# Load pyproject.toml
|
||||||
|
self.req.load_pyproject_toml()
|
||||||
|
|
||||||
|
# Set up the build isolation, if this requirement should be isolated
|
||||||
|
if build_isolation:
|
||||||
|
# Setup an isolated environment and install the build backend static
|
||||||
|
# requirements in it.
|
||||||
|
self._prepare_build_backend(build_env_installer)
|
||||||
|
# Check that the build backend supports PEP 660. This cannot be done
|
||||||
|
# earlier because we need to setup the build backend to verify it
|
||||||
|
# supports build_editable, nor can it be done later, because we want
|
||||||
|
# to avoid installing build requirements needlessly.
|
||||||
|
self.req.editable_sanity_check()
|
||||||
|
# Install the dynamic build requirements.
|
||||||
|
self._install_build_reqs(build_env_installer)
|
||||||
|
else:
|
||||||
|
# When not using build isolation, we still need to check that
|
||||||
|
# the build backend supports PEP 660.
|
||||||
|
self.req.editable_sanity_check()
|
||||||
|
# Check if the current environment provides build dependencies
|
||||||
|
if check_build_deps:
|
||||||
|
pyproject_requires = self.req.pyproject_requires
|
||||||
|
assert pyproject_requires is not None
|
||||||
|
conflicting, missing = self.req.build_env.check_requirements(
|
||||||
|
pyproject_requires
|
||||||
|
)
|
||||||
|
if conflicting:
|
||||||
|
self._raise_conflicts("the backend dependencies", conflicting)
|
||||||
|
if missing:
|
||||||
|
self._raise_missing_reqs(missing)
|
||||||
|
self.req.prepare_metadata()
|
||||||
|
|
||||||
|
def _prepare_build_backend(
|
||||||
|
self, build_env_installer: BuildEnvironmentInstaller
|
||||||
|
) -> None:
|
||||||
|
# Isolate in a BuildEnvironment and install the build-time
|
||||||
|
# requirements.
|
||||||
|
pyproject_requires = self.req.pyproject_requires
|
||||||
|
assert pyproject_requires is not None
|
||||||
|
|
||||||
|
self.req.build_env = BuildEnvironment(build_env_installer)
|
||||||
|
self.req.build_env.install_requirements(
|
||||||
|
pyproject_requires, "overlay", kind="build dependencies", for_req=self.req
|
||||||
|
)
|
||||||
|
conflicting, missing = self.req.build_env.check_requirements(
|
||||||
|
self.req.requirements_to_check
|
||||||
|
)
|
||||||
|
if conflicting:
|
||||||
|
self._raise_conflicts("PEP 517/518 supported requirements", conflicting)
|
||||||
|
if missing:
|
||||||
|
logger.warning(
|
||||||
|
"Missing build requirements in pyproject.toml for %s.",
|
||||||
|
self.req,
|
||||||
|
)
|
||||||
|
logger.warning(
|
||||||
|
"The project does not specify a build backend, and "
|
||||||
|
"pip cannot fall back to setuptools without %s.",
|
||||||
|
" and ".join(map(repr, sorted(missing))),
|
||||||
|
)
|
||||||
|
|
||||||
|
def _get_build_requires_wheel(self) -> Iterable[str]:
|
||||||
|
with self.req.build_env:
|
||||||
|
runner = runner_with_spinner_message("Getting requirements to build wheel")
|
||||||
|
backend = self.req.pep517_backend
|
||||||
|
assert backend is not None
|
||||||
|
with backend.subprocess_runner(runner):
|
||||||
|
return backend.get_requires_for_build_wheel()
|
||||||
|
|
||||||
|
def _get_build_requires_editable(self) -> Iterable[str]:
|
||||||
|
with self.req.build_env:
|
||||||
|
runner = runner_with_spinner_message(
|
||||||
|
"Getting requirements to build editable"
|
||||||
|
)
|
||||||
|
backend = self.req.pep517_backend
|
||||||
|
assert backend is not None
|
||||||
|
with backend.subprocess_runner(runner):
|
||||||
|
return backend.get_requires_for_build_editable()
|
||||||
|
|
||||||
|
def _install_build_reqs(
|
||||||
|
self, build_env_installer: BuildEnvironmentInstaller
|
||||||
|
) -> None:
|
||||||
|
# Install any extra build dependencies that the backend requests.
|
||||||
|
# This must be done in a second pass, as the pyproject.toml
|
||||||
|
# dependencies must be installed before we can call the backend.
|
||||||
|
if (
|
||||||
|
self.req.editable
|
||||||
|
and self.req.permit_editable_wheels
|
||||||
|
and self.req.supports_pyproject_editable
|
||||||
|
):
|
||||||
|
build_reqs = self._get_build_requires_editable()
|
||||||
|
else:
|
||||||
|
build_reqs = self._get_build_requires_wheel()
|
||||||
|
conflicting, missing = self.req.build_env.check_requirements(build_reqs)
|
||||||
|
if conflicting:
|
||||||
|
self._raise_conflicts("the backend dependencies", conflicting)
|
||||||
|
self.req.build_env.install_requirements(
|
||||||
|
missing, "normal", kind="backend dependencies", for_req=self.req
|
||||||
|
)
|
||||||
|
|
||||||
|
def _raise_conflicts(
|
||||||
|
self, conflicting_with: str, conflicting_reqs: set[tuple[str, str]]
|
||||||
|
) -> None:
|
||||||
|
format_string = (
|
||||||
|
"Some build dependencies for {requirement} "
|
||||||
|
"conflict with {conflicting_with}: {description}."
|
||||||
|
)
|
||||||
|
error_message = format_string.format(
|
||||||
|
requirement=self.req,
|
||||||
|
conflicting_with=conflicting_with,
|
||||||
|
description=", ".join(
|
||||||
|
f"{installed} is incompatible with {wanted}"
|
||||||
|
for installed, wanted in sorted(conflicting_reqs)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
raise InstallationError(error_message)
|
||||||
|
|
||||||
|
def _raise_missing_reqs(self, missing: set[str]) -> None:
|
||||||
|
format_string = (
|
||||||
|
"Some build dependencies for {requirement} are missing: {missing}."
|
||||||
|
)
|
||||||
|
error_message = format_string.format(
|
||||||
|
requirement=self.req, missing=", ".join(map(repr, sorted(missing)))
|
||||||
|
)
|
||||||
|
raise InstallationError(error_message)
|
||||||
44
venv/Lib/site-packages/pip/_internal/distributions/wheel.py
Normal file
44
venv/Lib/site-packages/pip/_internal/distributions/wheel.py
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
from pip._vendor.packaging.utils import canonicalize_name
|
||||||
|
|
||||||
|
from pip._internal.distributions.base import AbstractDistribution
|
||||||
|
from pip._internal.metadata import (
|
||||||
|
BaseDistribution,
|
||||||
|
FilesystemWheel,
|
||||||
|
get_wheel_distribution,
|
||||||
|
)
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from pip._internal.build_env import BuildEnvironmentInstaller
|
||||||
|
|
||||||
|
|
||||||
|
class WheelDistribution(AbstractDistribution):
|
||||||
|
"""Represents a wheel distribution.
|
||||||
|
|
||||||
|
This does not need any preparation as wheels can be directly unpacked.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@property
|
||||||
|
def build_tracker_id(self) -> str | None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_metadata_distribution(self) -> BaseDistribution:
|
||||||
|
"""Loads the metadata from the wheel file into memory and returns a
|
||||||
|
Distribution that uses it, not relying on the wheel file or
|
||||||
|
requirement.
|
||||||
|
"""
|
||||||
|
assert self.req.local_file_path, "Set as part of preparation during download"
|
||||||
|
assert self.req.name, "Wheels are never unnamed"
|
||||||
|
wheel = FilesystemWheel(self.req.local_file_path)
|
||||||
|
return get_wheel_distribution(wheel, canonicalize_name(self.req.name))
|
||||||
|
|
||||||
|
def prepare_distribution_metadata(
|
||||||
|
self,
|
||||||
|
build_env_installer: BuildEnvironmentInstaller,
|
||||||
|
build_isolation: bool,
|
||||||
|
check_build_deps: bool,
|
||||||
|
) -> None:
|
||||||
|
pass
|
||||||
Reference in New Issue
Block a user