From 93ec9a2b2a6689f5a224f10f759036f87274ffaa Mon Sep 17 00:00:00 2001 From: Tzu-ping Chung Date: Tue, 15 Dec 2020 17:08:35 +0800 Subject: [PATCH] Lazy-evaluate candidates with installed inserted --- news/9284.bugfix.rst | 2 ++ .../resolution/resolvelib/found_candidates.py | 28 +++++++++++-------- 2 files changed, 18 insertions(+), 12 deletions(-) create mode 100644 news/9284.bugfix.rst diff --git a/news/9284.bugfix.rst b/news/9284.bugfix.rst new file mode 100644 index 00000000000..6733980f72f --- /dev/null +++ b/news/9284.bugfix.rst @@ -0,0 +1,2 @@ +New resolver: Always iterate through candidates from indexes lazily to avoid +downloading candidates we do not need. diff --git a/src/pip/_internal/resolution/resolvelib/found_candidates.py b/src/pip/_internal/resolution/resolvelib/found_candidates.py index a669e893670..8aba4e527b0 100644 --- a/src/pip/_internal/resolution/resolvelib/found_candidates.py +++ b/src/pip/_internal/resolution/resolvelib/found_candidates.py @@ -1,5 +1,4 @@ import itertools -import operator from pip._vendor.six.moves import collections_abc # type: ignore @@ -32,18 +31,23 @@ def _insert_installed(installed, others): already-installed package. Candidates from index are returned in their normal ordering, except replaced when the version is already installed. - Since candidates from index are already sorted by reverse version order, - `sorted()` here would keep the ordering mostly intact, only shuffling the - already-installed candidate into the correct position. We put the already- - installed candidate in front of those from the index, so it's put in front - after sorting due to Python sorting's stableness guarentee. + The implementation iterates through and yields other candidates, but insert + the installed candidate exactly once before we start yielding older or + equivalent candidates, or after all other candidates if they are all newer. """ - candidates = sorted( - itertools.chain([installed], others), - key=operator.attrgetter("version"), - reverse=True, - ) - return iter(candidates) + installed_yielded = False + + for candidate in others: + # If the installed candidate if better, yield it first. + if not installed_yielded and installed.version >= candidate.version: + yield installed + installed_yielded = True + + yield candidate + + # If the installed candidate is older than all other candidates. + if not installed_yielded: + yield installed class FoundCandidates(collections_abc.Sequence):