summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPradyun Gedam <pradyunsg@users.noreply.github.com>2020-10-20 07:00:15 +0530
committerPradyun Gedam <pradyunsg@users.noreply.github.com>2020-10-27 19:32:35 +0530
commit95171c881fa8bc98b9dcd2f5c0c34cd7fce95904 (patch)
tree9e484802d5c4e3fd19206922adbc437d9f1cad8f
parent5bfd1db071c78c4bdcf2e80cc2142f1557d17d25 (diff)
downloadpip-95171c881fa8bc98b9dcd2f5c0c34cd7fce95904.tar.gz
Display messages when backtracking on a package
-rw-r--r--src/pip/_internal/resolution/resolvelib/reporter.py35
-rw-r--r--src/pip/_internal/resolution/resolvelib/resolver.py5
-rw-r--r--tests/functional/test_new_resolver.py45
3 files changed, 83 insertions, 2 deletions
diff --git a/src/pip/_internal/resolution/resolvelib/reporter.py b/src/pip/_internal/resolution/resolvelib/reporter.py
new file mode 100644
index 000000000..56e805975
--- /dev/null
+++ b/src/pip/_internal/resolution/resolvelib/reporter.py
@@ -0,0 +1,35 @@
+from collections import defaultdict
+from logging import getLogger
+
+from pip._vendor.resolvelib.reporters import BaseReporter
+
+logger = getLogger(__name__)
+
+
+class PipReporter(BaseReporter):
+
+ def __init__(self):
+ self.backtracks_by_package = defaultdict(int)
+
+ self._messages_at_backtrack = {
+ 8: (
+ "pip is looking at multiple versions of this package to determine "
+ "which version is compatible with other requirements. "
+ "This could take a while."
+ ),
+ 13: (
+ "This is taking longer than usual. You might need to provide the "
+ "dependency resolver with stricter constraints to reduce runtime."
+ "If you want to abort this run, you can press Ctrl + C to do so."
+ )
+ }
+
+ def backtracking(self, candidate):
+ self.backtracks_by_package[candidate.name] += 1
+
+ count = self.backtracks_by_package[candidate.name]
+ if count not in self._messages_at_backtrack:
+ return
+
+ message = self._messages_at_backtrack[count]
+ logger.info(message)
diff --git a/src/pip/_internal/resolution/resolvelib/resolver.py b/src/pip/_internal/resolution/resolvelib/resolver.py
index cb7d1ae8a..acb7cfeda 100644
--- a/src/pip/_internal/resolution/resolvelib/resolver.py
+++ b/src/pip/_internal/resolution/resolvelib/resolver.py
@@ -3,7 +3,7 @@ import logging
from pip._vendor import six
from pip._vendor.packaging.utils import canonicalize_name
-from pip._vendor.resolvelib import BaseReporter, ResolutionImpossible
+from pip._vendor.resolvelib import ResolutionImpossible
from pip._vendor.resolvelib import Resolver as RLResolver
from pip._internal.exceptions import InstallationError
@@ -11,6 +11,7 @@ from pip._internal.req.req_install import check_invalid_constraint_type
from pip._internal.req.req_set import RequirementSet
from pip._internal.resolution.base import BaseResolver
from pip._internal.resolution.resolvelib.provider import PipProvider
+from pip._internal.resolution.resolvelib.reporter import PipReporter
from pip._internal.utils.misc import dist_is_editable
from pip._internal.utils.typing import MYPY_CHECK_RUNNING
@@ -103,7 +104,7 @@ class Resolver(BaseResolver):
upgrade_strategy=self.upgrade_strategy,
user_requested=user_requested,
)
- reporter = BaseReporter()
+ reporter = PipReporter()
resolver = RLResolver(provider, reporter)
try:
diff --git a/tests/functional/test_new_resolver.py b/tests/functional/test_new_resolver.py
index 1718ab8a8..aa1744cc8 100644
--- a/tests/functional/test_new_resolver.py
+++ b/tests/functional/test_new_resolver.py
@@ -1046,3 +1046,48 @@ def test_new_resolver_prefers_installed_in_upgrade_if_latest(script):
"pkg",
)
assert_installed(script, pkg="2")
+
+
+@pytest.mark.parametrize("N", [10, 20])
+def test_new_resolver_presents_messages_when_backtracking_a_lot(script, N):
+ # Generate a set of wheels that will definitely cause backtracking.
+ for index in range(1, N+1):
+ A_version = "{index}.0.0".format(index=index)
+ B_version = "{index}.0.0".format(index=index)
+ C_version = "{index_minus_one}.0.0".format(index_minus_one=index - 1)
+
+ depends = ["B == " + B_version]
+ if index != 1:
+ depends.append("C == " + C_version)
+
+ print("A", A_version, "B", B_version, "C", C_version)
+ create_basic_wheel_for_package(script, "A", A_version, depends=depends)
+
+ for index in range(1, N+1):
+ B_version = "{index}.0.0".format(index=index)
+ C_version = "{index}.0.0".format(index=index)
+ depends = ["C == " + C_version]
+
+ print("B", B_version, "C", C_version)
+ create_basic_wheel_for_package(script, "B", B_version, depends=depends)
+
+ for index in range(1, N+1):
+ C_version = "{index}.0.0".format(index=index)
+ print("C", C_version)
+ create_basic_wheel_for_package(script, "C", C_version)
+
+ # Install A
+ result = script.pip(
+ "install",
+ "--use-feature=2020-resolver",
+ "--no-cache-dir",
+ "--no-index",
+ "--find-links", script.scratch_path,
+ "A"
+ )
+
+ assert_installed(script, A="1.0.0", B="1.0.0", C="1.0.0")
+ if N >= 8: # this number is hard-coded in the code too.
+ assert "This could take a while." in result.stdout
+ if N >= 13: # this number is hard-coded in the code too.
+ assert "press Ctrl + C" in result.stdout