|
5 | 5 | from pip._internal.exceptions import (
|
6 | 6 | DistributionNotFound,
|
7 | 7 | InstallationError,
|
| 8 | + InstallationSubprocessError, |
| 9 | + MetadataInconsistent, |
8 | 10 | UnsupportedPythonVersion,
|
9 | 11 | UnsupportedWheel,
|
10 | 12 | )
|
|
33 | 35 | ExplicitRequirement,
|
34 | 36 | RequiresPythonRequirement,
|
35 | 37 | SpecifierRequirement,
|
| 38 | + UnsatisfiableRequirement, |
36 | 39 | )
|
37 | 40 |
|
38 | 41 | if MYPY_CHECK_RUNNING:
|
@@ -96,6 +99,7 @@ def __init__(
|
96 | 99 |
|
97 | 100 | self._link_candidate_cache = {} # type: Cache[LinkCandidate]
|
98 | 101 | self._editable_candidate_cache = {} # type: Cache[EditableCandidate]
|
| 102 | + self._build_failures = {} # type: Cache[InstallationError] |
99 | 103 |
|
100 | 104 | if not ignore_installed:
|
101 | 105 | self._installed_dists = {
|
@@ -130,20 +134,34 @@ def _make_candidate_from_link(
|
130 | 134 | name, # type: Optional[str]
|
131 | 135 | version, # type: Optional[_BaseVersion]
|
132 | 136 | ):
|
133 |
| - # type: (...) -> Candidate |
| 137 | + # type: (...) -> Optional[Candidate] |
134 | 138 | # TODO: Check already installed candidate, and use it if the link and
|
135 | 139 | # editable flag match.
|
| 140 | + if link in self._build_failures: |
| 141 | + return None |
136 | 142 | if template.editable:
|
137 | 143 | if link not in self._editable_candidate_cache:
|
138 |
| - self._editable_candidate_cache[link] = EditableCandidate( |
139 |
| - link, template, factory=self, name=name, version=version, |
140 |
| - ) |
| 144 | + try: |
| 145 | + self._editable_candidate_cache[link] = EditableCandidate( |
| 146 | + link, template, factory=self, |
| 147 | + name=name, version=version, |
| 148 | + ) |
| 149 | + except (InstallationSubprocessError, MetadataInconsistent) as e: |
| 150 | + logger.warning("Discarding %s. %s", link, e) |
| 151 | + self._build_failures[link] = e |
| 152 | + return None |
141 | 153 | base = self._editable_candidate_cache[link] # type: BaseCandidate
|
142 | 154 | else:
|
143 | 155 | if link not in self._link_candidate_cache:
|
144 |
| - self._link_candidate_cache[link] = LinkCandidate( |
145 |
| - link, template, factory=self, name=name, version=version, |
146 |
| - ) |
| 156 | + try: |
| 157 | + self._link_candidate_cache[link] = LinkCandidate( |
| 158 | + link, template, factory=self, |
| 159 | + name=name, version=version, |
| 160 | + ) |
| 161 | + except (InstallationSubprocessError, MetadataInconsistent) as e: |
| 162 | + logger.warning("Discarding %s. %s", link, e) |
| 163 | + self._build_failures[link] = e |
| 164 | + return None |
147 | 165 | base = self._link_candidate_cache[link]
|
148 | 166 | if extras:
|
149 | 167 | return ExtrasCandidate(base, extras)
|
@@ -204,13 +222,16 @@ def iter_index_candidates():
|
204 | 222 | for ican in reversed(icans):
|
205 | 223 | if not all_yanked and ican.link.is_yanked:
|
206 | 224 | continue
|
207 |
| - yield self._make_candidate_from_link( |
| 225 | + candidate = self._make_candidate_from_link( |
208 | 226 | link=ican.link,
|
209 | 227 | extras=extras,
|
210 | 228 | template=template,
|
211 | 229 | name=name,
|
212 | 230 | version=ican.version,
|
213 | 231 | )
|
| 232 | + if candidate is None: |
| 233 | + continue |
| 234 | + yield candidate |
214 | 235 |
|
215 | 236 | return FoundCandidates(
|
216 | 237 | iter_index_candidates,
|
@@ -274,6 +295,10 @@ def make_requirement_from_install_req(self, ireq, requested_extras):
|
274 | 295 | name=canonicalize_name(ireq.name) if ireq.name else None,
|
275 | 296 | version=None,
|
276 | 297 | )
|
| 298 | + if cand is None: |
| 299 | + if not ireq.name: |
| 300 | + raise self._build_failures[ireq.link] |
| 301 | + return UnsatisfiableRequirement(canonicalize_name(ireq.name)) |
277 | 302 | return self.make_requirement_from_candidate(cand)
|
278 | 303 |
|
279 | 304 | def make_requirement_from_candidate(self, candidate):
|
|
0 commit comments