Buckets:
| """Utilities to lazily create and visit candidates found. | |
| Creating and visiting a candidate is a *very* costly operation. It involves | |
| fetching, extracting, potentially building modules from source, and verifying | |
| distribution metadata. It is therefore crucial for performance to keep | |
| everything here lazy all the way down, so we only touch candidates that we | |
| absolutely need, and not "download the world" when we only need one version of | |
| something. | |
| """ | |
| from __future__ import annotations | |
| import logging | |
| from collections.abc import Iterator, Sequence | |
| from typing import Any, Callable, Optional | |
| from pip._vendor.packaging.version import _BaseVersion | |
| from pip._internal.exceptions import MetadataInvalid | |
| from .base import Candidate | |
| logger = logging.getLogger(__name__) | |
| IndexCandidateInfo = tuple[_BaseVersion, Callable[[], Optional[Candidate]]] | |
| def _iter_built(infos: Iterator[IndexCandidateInfo]) -> Iterator[Candidate]: | |
| """Iterator for ``FoundCandidates``. | |
| This iterator is used when the package is not already installed. Candidates | |
| from index come later in their normal ordering. | |
| """ | |
| versions_found: set[_BaseVersion] = set() | |
| for version, func in infos: | |
| if version in versions_found: | |
| continue | |
| try: | |
| candidate = func() | |
| except MetadataInvalid as e: | |
| logger.warning( | |
| "Ignoring version %s of %s since it has invalid metadata:\n" | |
| "%s\n" | |
| "Please use pip<24.1 if you need to use this version.", | |
| version, | |
| e.ireq.name, | |
| e, | |
| ) | |
| # Mark version as found to avoid trying other candidates with the same | |
| # version, since they most likely have invalid metadata as well. | |
| versions_found.add(version) | |
| else: | |
| if candidate is None: | |
| continue | |
| yield candidate | |
| versions_found.add(version) | |
| def _iter_built_with_prepended( | |
| installed: Candidate, infos: Iterator[IndexCandidateInfo] | |
| ) -> Iterator[Candidate]: | |
| """Iterator for ``FoundCandidates``. | |
| This iterator is used when the resolver prefers the already-installed | |
| candidate and NOT to upgrade. The installed candidate is therefore | |
| always yielded first, and candidates from index come later in their | |
| normal ordering, except skipped when the version is already installed. | |
| """ | |
| yield installed | |
| versions_found: set[_BaseVersion] = {installed.version} | |
| for version, func in infos: | |
| if version in versions_found: | |
| continue | |
| candidate = func() | |
| if candidate is None: | |
| continue | |
| yield candidate | |
| versions_found.add(version) | |
| def _iter_built_with_inserted( | |
| installed: Candidate, infos: Iterator[IndexCandidateInfo] | |
| ) -> Iterator[Candidate]: | |
| """Iterator for ``FoundCandidates``. | |
| This iterator is used when the resolver prefers to upgrade an | |
| already-installed package. Candidates from index are returned in their | |
| normal ordering, except replaced when the version is already installed. | |
| The implementation iterates through and yields other candidates, inserting | |
| the installed candidate exactly once before we start yielding older or | |
| equivalent candidates, or after all other candidates if they are all newer. | |
| """ | |
| versions_found: set[_BaseVersion] = set() | |
| for version, func in infos: | |
| if version in versions_found: | |
| continue | |
| # If the installed candidate is better, yield it first. | |
| if installed.version >= version: | |
| yield installed | |
| versions_found.add(installed.version) | |
| candidate = func() | |
| if candidate is None: | |
| continue | |
| yield candidate | |
| versions_found.add(version) | |
| # If the installed candidate is older than all other candidates. | |
| if installed.version not in versions_found: | |
| yield installed | |
| class FoundCandidates(Sequence[Candidate]): | |
| """A lazy sequence to provide candidates to the resolver. | |
| The intended usage is to return this from `find_matches()` so the resolver | |
| can iterate through the sequence multiple times, but only access the index | |
| page when remote packages are actually needed. This improve performances | |
| when suitable candidates are already installed on disk. | |
| """ | |
| def __init__( | |
| self, | |
| get_infos: Callable[[], Iterator[IndexCandidateInfo]], | |
| installed: Candidate | None, | |
| prefers_installed: bool, | |
| incompatible_ids: set[int], | |
| ): | |
| self._get_infos = get_infos | |
| self._installed = installed | |
| self._prefers_installed = prefers_installed | |
| self._incompatible_ids = incompatible_ids | |
| self._bool: bool | None = None | |
| def __getitem__(self, index: Any) -> Any: | |
| # Implemented to satisfy the ABC check. This is not needed by the | |
| # resolver, and should not be used by the provider either (for | |
| # performance reasons). | |
| raise NotImplementedError("don't do this") | |
| def __iter__(self) -> Iterator[Candidate]: | |
| infos = self._get_infos() | |
| if not self._installed: | |
| iterator = _iter_built(infos) | |
| elif self._prefers_installed: | |
| iterator = _iter_built_with_prepended(self._installed, infos) | |
| else: | |
| iterator = _iter_built_with_inserted(self._installed, infos) | |
| return (c for c in iterator if id(c) not in self._incompatible_ids) | |
| def __len__(self) -> int: | |
| # Implemented to satisfy the ABC check. This is not needed by the | |
| # resolver, and should not be used by the provider either (for | |
| # performance reasons). | |
| raise NotImplementedError("don't do this") | |
| def __bool__(self) -> bool: | |
| if self._bool is not None: | |
| return self._bool | |
| if self._prefers_installed and self._installed: | |
| self._bool = True | |
| return True | |
| self._bool = any(self) | |
| return self._bool | |
Xet Storage Details
- Size:
- 6.02 kB
- Xet hash:
- e707a04ceec598dea940a728737620421384ee8abc345c16655b3aa7ca06cdc5
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.