diff --git a/news/8924.feature b/news/8924.feature new file mode 100644 index 000000000..c607aa0d0 --- /dev/null +++ b/news/8924.feature @@ -0,0 +1,2 @@ +New resolver: Tweak resolution logic to improve user experience when +user-supplied requirements conflict. diff --git a/src/pip/_internal/resolution/resolvelib/provider.py b/src/pip/_internal/resolution/resolvelib/provider.py index a1bab05a4..8264b471c 100644 --- a/src/pip/_internal/resolution/resolvelib/provider.py +++ b/src/pip/_internal/resolution/resolvelib/provider.py @@ -43,7 +43,7 @@ class PipProvider(AbstractProvider): self._constraints = constraints self._ignore_dependencies = ignore_dependencies self._upgrade_strategy = upgrade_strategy - self.user_requested = user_requested + self._user_requested = user_requested def _sort_matches(self, matches): # type: (Iterable[Candidate]) -> Sequence[Candidate] @@ -84,7 +84,7 @@ class PipProvider(AbstractProvider): if self._upgrade_strategy == "eager": return True elif self._upgrade_strategy == "only-if-needed": - return (name in self.user_requested) + return (name in self._user_requested) return False def sort_key(c): @@ -115,11 +115,18 @@ class PipProvider(AbstractProvider): self, resolution, # type: Optional[Candidate] candidates, # type: Sequence[Candidate] - information # type: Sequence[Tuple[Requirement, Candidate]] + information # type: Sequence[Tuple[Requirement, Optional[Candidate]]] ): # type: (...) -> Any - # Use the "usual" value for now - return len(candidates) + """Return a sort key to determine what dependency to look next. + + A smaller value makes a dependency higher priority. We put direct + (user-requested) dependencies first since they may contain useful + user-specified version ranges. Users tend to expect us to catch + problems in them early as well. + """ + transitive = all(parent is not None for _, parent in information) + return (transitive, len(candidates)) def find_matches(self, requirements): # type: (Sequence[Requirement]) -> Iterable[Candidate]