From 3642589903743be36449f4e6f8d9a8c091e5c594 Mon Sep 17 00:00:00 2001
From: Paul Moore
Date: Mon, 13 Apr 2020 11:16:30 +0100
Subject: [PATCH 1/2] Make message more user friendly when unable to resolve
---
.../resolution/resolvelib/requirements.py | 4 +++
.../resolution/resolvelib/resolver.py | 28 ++++++++++++++--
tests/functional/test_new_resolver.py | 33 +++++++++++++++++++
3 files changed, 63 insertions(+), 2 deletions(-)
diff --git a/src/pip/_internal/resolution/resolvelib/requirements.py b/src/pip/_internal/resolution/resolvelib/requirements.py
index 027e36aa61e..952973ae7cc 100644
--- a/src/pip/_internal/resolution/resolvelib/requirements.py
+++ b/src/pip/_internal/resolution/resolvelib/requirements.py
@@ -79,6 +79,10 @@ def __init__(self, ireq, factory):
self._factory = factory
self.extras = ireq.req.extras
+ def __str__(self):
+ # type: () -> str
+ return str(self._ireq.req)
+
def __repr__(self):
# type: () -> str
return "{class_name}({requirement!r})".format(
diff --git a/src/pip/_internal/resolution/resolvelib/resolver.py b/src/pip/_internal/resolution/resolvelib/resolver.py
index 5e6408573c6..d2e571f17bf 100644
--- a/src/pip/_internal/resolution/resolvelib/resolver.py
+++ b/src/pip/_internal/resolution/resolvelib/resolver.py
@@ -1,9 +1,11 @@
import functools
+import logging
from pip._vendor.packaging.utils import canonicalize_name
-from pip._vendor.resolvelib import BaseReporter
+from pip._vendor.resolvelib import BaseReporter, ResolutionImpossible
from pip._vendor.resolvelib import Resolver as RLResolver
+from pip._internal.exceptions import InstallationError
from pip._internal.req.req_set import RequirementSet
from pip._internal.resolution.base import BaseResolver
from pip._internal.resolution.resolvelib.provider import PipProvider
@@ -23,6 +25,9 @@
from pip._internal.resolution.base import InstallRequirementProvider
+logger = logging.getLogger(__name__)
+
+
class Resolver(BaseResolver):
def __init__(
self,
@@ -64,7 +69,26 @@ def resolve(self, root_reqs, check_supported_wheels):
self.factory.make_requirement_from_install_req(r)
for r in root_reqs
]
- self._result = resolver.resolve(requirements)
+
+ try:
+ self._result = resolver.resolve(requirements)
+ except ResolutionImpossible as exc:
+ # TODO: This is just an initial version. May need more work.
+ # Also could do with rewriting to fit better into 80-char
+ # lines :-(
+ for req, parent in exc.causes:
+ logger.critical(
+ "Could not find a version that satisfies " +
+ "the requirement " +
+ str(req) +
+ ("" if parent is None else " (from {})".format(
+ parent.name
+ ))
+ )
+ raise InstallationError(
+ "No matching distribution found for " +
+ ", ".join([r.name for r, _ in exc.causes])
+ )
req_set = RequirementSet(check_supported_wheels=check_supported_wheels)
for candidate in self._result.mapping.values():
diff --git a/tests/functional/test_new_resolver.py b/tests/functional/test_new_resolver.py
index 25c726f2574..5d119865e7f 100644
--- a/tests/functional/test_new_resolver.py
+++ b/tests/functional/test_new_resolver.py
@@ -155,6 +155,39 @@ def test_new_resolver_installs_extras(script):
assert_installed(script, base="0.1.0", dep="0.1.0")
+def test_new_resolver_installed_message(script):
+ create_basic_wheel_for_package(script, "A", "1.0")
+ result = script.pip(
+ "install", "--unstable-feature=resolver",
+ "--no-cache-dir", "--no-index",
+ "--find-links", script.scratch_path,
+ "A",
+ expect_stderr=False,
+ )
+ assert "Successfully installed A-1.0" in result.stdout, str(result)
+
+
+def test_new_resolver_no_dist_message(script):
+ create_basic_wheel_for_package(script, "A", "1.0")
+ result = script.pip(
+ "install", "--unstable-feature=resolver",
+ "--no-cache-dir", "--no-index",
+ "--find-links", script.scratch_path,
+ "B",
+ expect_error=True,
+ expect_stderr=True,
+ )
+
+ # Full messages from old resolver:
+ # ERROR: Could not find a version that satisfies the
+ # requirement xxx (from versions: none)
+ # ERROR: No matching distribution found for xxx
+
+ assert "Could not find a version that satisfies the requirement B" \
+ in result.stderr, str(result)
+ assert "No matching distribution found for B" in result.stderr, str(result)
+
+
def test_new_resolver_installs_editable(script):
create_basic_wheel_for_package(
script,
From 8c118c8f3a6fd850e49256c51440142526a3d7c6 Mon Sep 17 00:00:00 2001
From: Paul Moore
Date: Tue, 14 Apr 2020 15:18:24 +0100
Subject: [PATCH 2/2] Fix the test to check for canonical name
---
tests/functional/test_new_resolver.py | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/tests/functional/test_new_resolver.py b/tests/functional/test_new_resolver.py
index 73ceff9aaea..cb384d7a0ac 100644
--- a/tests/functional/test_new_resolver.py
+++ b/tests/functional/test_new_resolver.py
@@ -186,7 +186,9 @@ def test_new_resolver_no_dist_message(script):
assert "Could not find a version that satisfies the requirement B" \
in result.stderr, str(result)
- assert "No matching distribution found for B" in result.stderr, str(result)
+ # TODO: This reports the canonical name of the project. But the current
+ # resolver reports the originally specified name (i.e. uppercase B)
+ assert "No matching distribution found for b" in result.stderr, str(result)
def test_new_resolver_installs_editable(script):