mirror of https://github.com/pypa/pip
Exclude a known incompatible installed candidate
The resolver collects previously known incompatibilites and sends them to the provider. But previously the provider does not correctly exclude the currently-installed candidate if it is present in that incompatibility list, causing the resolver to enter a loop trying that same candidate. This patch correctly applies incompat_ids when producing an AlreadyInstalledCandidate and exclude it if its id() is in the set.
This commit is contained in:
parent
1c31d3314c
commit
729c626da7
|
@ -0,0 +1,3 @@
|
||||||
|
New resolver: Correctly exclude an already installed package if its version is
|
||||||
|
known to be incompatible to stop the dependency resolution process with a clear
|
||||||
|
error message.
|
|
@ -240,18 +240,29 @@ class Factory:
|
||||||
hashes &= ireq.hashes(trust_internet=False)
|
hashes &= ireq.hashes(trust_internet=False)
|
||||||
extras |= frozenset(ireq.extras)
|
extras |= frozenset(ireq.extras)
|
||||||
|
|
||||||
# Get the installed version, if it matches, unless the user
|
def _get_installed_candidate() -> Optional[Candidate]:
|
||||||
# specified `--force-reinstall`, when we want the version from
|
"""Get the candidate for the currently-installed version."""
|
||||||
# the index instead.
|
# If --force-reinstall is set, we want the version from the index
|
||||||
installed_candidate = None
|
# instead, so we "pretend" there is nothing installed.
|
||||||
if not self._force_reinstall and name in self._installed_dists:
|
if self._force_reinstall:
|
||||||
installed_dist = self._installed_dists[name]
|
return None
|
||||||
if specifier.contains(installed_dist.version, prereleases=True):
|
try:
|
||||||
installed_candidate = self._make_candidate_from_dist(
|
installed_dist = self._installed_dists[name]
|
||||||
dist=installed_dist,
|
except KeyError:
|
||||||
extras=extras,
|
return None
|
||||||
template=template,
|
# Don't use the installed distribution if its version does not fit
|
||||||
)
|
# the current dependency graph.
|
||||||
|
if not specifier.contains(installed_dist.version, prereleases=True):
|
||||||
|
return None
|
||||||
|
candidate = self._make_candidate_from_dist(
|
||||||
|
dist=installed_dist,
|
||||||
|
extras=extras,
|
||||||
|
template=template,
|
||||||
|
)
|
||||||
|
# The candidate is a known incompatiblity. Don't use it.
|
||||||
|
if id(candidate) in incompatible_ids:
|
||||||
|
return None
|
||||||
|
return candidate
|
||||||
|
|
||||||
def iter_index_candidate_infos():
|
def iter_index_candidate_infos():
|
||||||
# type: () -> Iterator[IndexCandidateInfo]
|
# type: () -> Iterator[IndexCandidateInfo]
|
||||||
|
@ -283,7 +294,7 @@ class Factory:
|
||||||
|
|
||||||
return FoundCandidates(
|
return FoundCandidates(
|
||||||
iter_index_candidate_infos,
|
iter_index_candidate_infos,
|
||||||
installed_candidate,
|
_get_installed_candidate(),
|
||||||
prefers_installed,
|
prefers_installed,
|
||||||
incompatible_ids,
|
incompatible_ids,
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in New Issue