Загрузить файлы в «venv/Lib/site-packages/pip/_internal/models»

This commit is contained in:
2026-07-02 19:03:57 +00:00
parent a866d147ed
commit 6a6565bbf9
3 changed files with 258 additions and 0 deletions

View File

@@ -0,0 +1,56 @@
from __future__ import annotations
from pip._internal.models.format_control import FormatControl
from pip._internal.models.release_control import ReleaseControl
# TODO: This needs Python 3.10's improved slots support for dataclasses
# to be converted into a dataclass.
class SelectionPreferences:
"""
Encapsulates the candidate selection preferences for downloading
and installing files.
"""
__slots__ = [
"allow_yanked",
"release_control",
"format_control",
"prefer_binary",
"ignore_requires_python",
]
# Don't include an allow_yanked default value to make sure each call
# site considers whether yanked releases are allowed. This also causes
# that decision to be made explicit in the calling code, which helps
# people when reading the code.
def __init__(
self,
allow_yanked: bool,
release_control: ReleaseControl | None = None,
format_control: FormatControl | None = None,
prefer_binary: bool = False,
ignore_requires_python: bool | None = None,
) -> None:
"""Create a SelectionPreferences object.
:param allow_yanked: Whether files marked as yanked (in the sense
of PEP 592) are permitted to be candidates for install.
:param release_control: A ReleaseControl object or None. Used to control
whether pre-releases are allowed for specific packages.
:param format_control: A FormatControl object or None. Used to control
the selection of source packages / binary packages when consulting
the index and links.
:param prefer_binary: Whether to prefer an old, but valid, binary
dist over a new source dist.
:param ignore_requires_python: Whether to ignore incompatible
"Requires-Python" values in links. Defaults to False.
"""
if ignore_requires_python is None:
ignore_requires_python = False
self.allow_yanked = allow_yanked
self.release_control = release_control
self.format_control = format_control
self.prefer_binary = prefer_binary
self.ignore_requires_python = ignore_requires_python

View File

@@ -0,0 +1,122 @@
from __future__ import annotations
import sys
from pip._vendor.packaging.tags import Tag
from pip._internal.utils.compatibility_tags import get_supported, version_info_to_nodot
from pip._internal.utils.misc import normalize_version_info
class TargetPython:
"""
Encapsulates the properties of a Python interpreter one is targeting
for a package install, download, etc.
"""
__slots__ = [
"_given_py_version_info",
"abis",
"implementation",
"platforms",
"py_version",
"py_version_info",
"_valid_tags",
"_valid_tags_set",
]
def __init__(
self,
platforms: list[str] | None = None,
py_version_info: tuple[int, ...] | None = None,
abis: list[str] | None = None,
implementation: str | None = None,
) -> None:
"""
:param platforms: A list of strings or None. If None, searches for
packages that are supported by the current system. Otherwise, will
find packages that can be built on the platforms passed in. These
packages will only be downloaded for distribution: they will
not be built locally.
:param py_version_info: An optional tuple of ints representing the
Python version information to use (e.g. `sys.version_info[:3]`).
This can have length 1, 2, or 3 when provided.
:param abis: A list of strings or None. This is passed to
compatibility_tags.py's get_supported() function as is.
:param implementation: A string or None. This is passed to
compatibility_tags.py's get_supported() function as is.
"""
# Store the given py_version_info for when we call get_supported().
self._given_py_version_info = py_version_info
if py_version_info is None:
py_version_info = sys.version_info[:3]
else:
py_version_info = normalize_version_info(py_version_info)
py_version = ".".join(map(str, py_version_info[:2]))
self.abis = abis
self.implementation = implementation
self.platforms = platforms
self.py_version = py_version
self.py_version_info = py_version_info
# This is used to cache the return value of get_(un)sorted_tags.
self._valid_tags: list[Tag] | None = None
self._valid_tags_set: set[Tag] | None = None
def format_given(self) -> str:
"""
Format the given, non-None attributes for display.
"""
display_version = None
if self._given_py_version_info is not None:
display_version = ".".join(
str(part) for part in self._given_py_version_info
)
key_values = [
("platforms", self.platforms),
("version_info", display_version),
("abis", self.abis),
("implementation", self.implementation),
]
return " ".join(
f"{key}={value!r}" for key, value in key_values if value is not None
)
def get_sorted_tags(self) -> list[Tag]:
"""
Return the supported PEP 425 tags to check wheel candidates against.
The tags are returned in order of preference (most preferred first).
"""
if self._valid_tags is None:
# Pass versions=None if no py_version_info was given since
# versions=None uses special default logic.
py_version_info = self._given_py_version_info
if py_version_info is None:
version = None
else:
version = version_info_to_nodot(py_version_info)
tags = get_supported(
version=version,
platforms=self.platforms,
abis=self.abis,
impl=self.implementation,
)
self._valid_tags = tags
return self._valid_tags
def get_unsorted_tags(self) -> set[Tag]:
"""Exactly the same as get_sorted_tags, but returns a set.
This is important for performance.
"""
if self._valid_tags_set is None:
self._valid_tags_set = set(self.get_sorted_tags())
return self._valid_tags_set

View File

@@ -0,0 +1,80 @@
"""Represents a wheel file and provides access to the various parts of the
name that have meaning.
"""
from __future__ import annotations
from collections.abc import Iterable
from pip._vendor.packaging.tags import Tag
from pip._vendor.packaging.utils import (
InvalidWheelFilename as _PackagingInvalidWheelFilename,
)
from pip._vendor.packaging.utils import parse_wheel_filename
from pip._internal.exceptions import InvalidWheelFilename
class Wheel:
"""A wheel file"""
def __init__(self, filename: str) -> None:
self.filename = filename
try:
wheel_info = parse_wheel_filename(filename)
except _PackagingInvalidWheelFilename as e:
raise InvalidWheelFilename(e.args[0]) from None
self.name, _version, self.build_tag, self.file_tags = wheel_info
self.version = str(_version)
def get_formatted_file_tags(self) -> list[str]:
"""Return the wheel's tags as a sorted list of strings."""
return sorted(str(tag) for tag in self.file_tags)
def support_index_min(self, tags: list[Tag]) -> int:
"""Return the lowest index that one of the wheel's file_tag combinations
achieves in the given list of supported tags.
For example, if there are 8 supported tags and one of the file tags
is first in the list, then return 0.
:param tags: the PEP 425 tags to check the wheel against, in order
with most preferred first.
:raises ValueError: If none of the wheel's file tags match one of
the supported tags.
"""
try:
return next(i for i, t in enumerate(tags) if t in self.file_tags)
except StopIteration:
raise ValueError()
def find_most_preferred_tag(
self, tags: list[Tag], tag_to_priority: dict[Tag, int]
) -> int:
"""Return the priority of the most preferred tag that one of the wheel's file
tag combinations achieves in the given list of supported tags using the given
tag_to_priority mapping, where lower priorities are more-preferred.
This is used in place of support_index_min in some cases in order to avoid
an expensive linear scan of a large list of tags.
:param tags: the PEP 425 tags to check the wheel against.
:param tag_to_priority: a mapping from tag to priority of that tag, where
lower is more preferred.
:raises ValueError: If none of the wheel's file tags match one of
the supported tags.
"""
return min(
tag_to_priority[tag] for tag in self.file_tags if tag in tag_to_priority
)
def supported(self, tags: Iterable[Tag]) -> bool:
"""Return whether the wheel is compatible with one of the given tags.
:param tags: the PEP 425 tags to check the wheel against.
"""
return not self.file_tags.isdisjoint(tags)