|
| 1 | +import collections |
| 2 | + |
| 3 | +from pip._vendor import six |
1 | 4 | from pip._vendor.packaging.utils import canonicalize_name
|
2 | 5 |
|
3 | 6 | from pip._internal.exceptions import (
|
|
44 | 47 |
|
45 | 48 | C = TypeVar("C")
|
46 | 49 | Cache = Dict[Link, C]
|
| 50 | + VersionCandidates = Dict[_BaseVersion, Candidate] |
47 | 51 |
|
48 | 52 |
|
49 | 53 | class Factory(object):
|
@@ -127,40 +131,44 @@ def iter_found_candidates(self, ireq, extras):
|
127 | 131 | # requirement needs to return only one candidate per version, so we
|
128 | 132 | # implement that logic here so that requirements using this helper
|
129 | 133 | # don't all have to do the same thing later.
|
130 |
| - seen_versions = set() # type: Set[_BaseVersion] |
| 134 | + candidates = collections.OrderedDict() # type: VersionCandidates |
131 | 135 |
|
132 | 136 | # Yield the installed version, if it matches, unless the user
|
133 | 137 | # specified `--force-reinstall`, when we want the version from
|
134 | 138 | # the index instead.
|
| 139 | + installed_version = None |
135 | 140 | if not self._force_reinstall and name in self._installed_dists:
|
136 | 141 | installed_dist = self._installed_dists[name]
|
137 | 142 | installed_version = installed_dist.parsed_version
|
138 | 143 | if ireq.req.specifier.contains(
|
139 | 144 | installed_version,
|
140 | 145 | prereleases=True
|
141 | 146 | ):
|
142 |
| - seen_versions.add(installed_version) |
143 |
| - yield self._make_candidate_from_dist( |
| 147 | + candidate = self._make_candidate_from_dist( |
144 | 148 | dist=installed_dist,
|
145 | 149 | extras=extras,
|
146 | 150 | parent=ireq,
|
147 | 151 | )
|
| 152 | + candidates[installed_version] = candidate |
148 | 153 |
|
149 | 154 | found = self.finder.find_best_candidate(
|
150 | 155 | project_name=ireq.req.name,
|
151 | 156 | specifier=ireq.req.specifier,
|
152 | 157 | hashes=ireq.hashes(trust_internet=False),
|
153 | 158 | )
|
154 | 159 | 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) |
164 | 172 |
|
165 | 173 | def make_requirement_from_install_req(self, ireq):
|
166 | 174 | # type: (InstallRequirement) -> Requirement
|
|
0 commit comments