Skip to content

Commit c65625b

Browse files
authored
Merge pull request #8256 from uranusjr/new-resolver-candidate-order
Use OrderedDict to prefer links found later
2 parents 301f65f + f391346 commit c65625b

File tree

1 file changed

+20
-12
lines changed

1 file changed

+20
-12
lines changed

src/pip/_internal/resolution/resolvelib/factory.py

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import collections
2+
3+
from pip._vendor import six
14
from pip._vendor.packaging.utils import canonicalize_name
25

36
from pip._internal.exceptions import (
@@ -44,6 +47,7 @@
4447

4548
C = TypeVar("C")
4649
Cache = Dict[Link, C]
50+
VersionCandidates = Dict[_BaseVersion, Candidate]
4751

4852

4953
class Factory(object):
@@ -127,40 +131,44 @@ def iter_found_candidates(self, ireq, extras):
127131
# requirement needs to return only one candidate per version, so we
128132
# implement that logic here so that requirements using this helper
129133
# don't all have to do the same thing later.
130-
seen_versions = set() # type: Set[_BaseVersion]
134+
candidates = collections.OrderedDict() # type: VersionCandidates
131135

132136
# Yield the installed version, if it matches, unless the user
133137
# specified `--force-reinstall`, when we want the version from
134138
# the index instead.
139+
installed_version = None
135140
if not self._force_reinstall and name in self._installed_dists:
136141
installed_dist = self._installed_dists[name]
137142
installed_version = installed_dist.parsed_version
138143
if ireq.req.specifier.contains(
139144
installed_version,
140145
prereleases=True
141146
):
142-
seen_versions.add(installed_version)
143-
yield self._make_candidate_from_dist(
147+
candidate = self._make_candidate_from_dist(
144148
dist=installed_dist,
145149
extras=extras,
146150
parent=ireq,
147151
)
152+
candidates[installed_version] = candidate
148153

149154
found = self.finder.find_best_candidate(
150155
project_name=ireq.req.name,
151156
specifier=ireq.req.specifier,
152157
hashes=ireq.hashes(trust_internet=False),
153158
)
154159
for ican in found.iter_applicable():
155-
if ican.version not in seen_versions:
156-
seen_versions.add(ican.version)
157-
yield self._make_candidate_from_link(
158-
link=ican.link,
159-
extras=extras,
160-
parent=ireq,
161-
name=name,
162-
version=ican.version,
163-
)
160+
if ican.version == installed_version:
161+
continue
162+
candidate = self._make_candidate_from_link(
163+
link=ican.link,
164+
extras=extras,
165+
parent=ireq,
166+
name=name,
167+
version=ican.version,
168+
)
169+
candidates[ican.version] = candidate
170+
171+
return six.itervalues(candidates)
164172

165173
def make_requirement_from_install_req(self, ireq):
166174
# type: (InstallRequirement) -> Requirement

0 commit comments

Comments
 (0)