From ebc13756128b8f85ce1ea76cd5f507e7d0c928d4 Mon Sep 17 00:00:00 2001 From: Tzu-ping Chung Date: Sat, 26 Sep 2020 16:06:44 +0800 Subject: [PATCH 1/3] Make private attribute looks private --- src/pip/_internal/resolution/resolvelib/provider.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pip/_internal/resolution/resolvelib/provider.py b/src/pip/_internal/resolution/resolvelib/provider.py index a1bab05a484..8ad1c65d352 100644 --- a/src/pip/_internal/resolution/resolvelib/provider.py +++ b/src/pip/_internal/resolution/resolvelib/provider.py @@ -43,7 +43,7 @@ def __init__( 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 @@ def _eligible_for_upgrade(name): 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): From c2de8974d422596909c2700636dff07dd3bf1225 Mon Sep 17 00:00:00 2001 From: Tzu-ping Chung Date: Sun, 27 Sep 2020 23:16:25 +0800 Subject: [PATCH 2/3] Resolve user-requested requirements first --- src/pip/_internal/resolution/resolvelib/provider.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/pip/_internal/resolution/resolvelib/provider.py b/src/pip/_internal/resolution/resolvelib/provider.py index 8ad1c65d352..8264b471c90 100644 --- a/src/pip/_internal/resolution/resolvelib/provider.py +++ b/src/pip/_internal/resolution/resolvelib/provider.py @@ -115,11 +115,18 @@ def get_preference( 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] From df6d3c701a02e7bcea71ae932f2f02917894664a Mon Sep 17 00:00:00 2001 From: Tzu-ping Chung Date: Mon, 28 Sep 2020 22:22:58 +0800 Subject: [PATCH 3/3] News fragment --- news/8924.feature | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 news/8924.feature diff --git a/news/8924.feature b/news/8924.feature new file mode 100644 index 00000000000..c607aa0d06b --- /dev/null +++ b/news/8924.feature @@ -0,0 +1,2 @@ +New resolver: Tweak resolution logic to improve user experience when +user-supplied requirements conflict.