diff options
author | Pradyun Gedam <pradyunsg@users.noreply.github.com> | 2020-10-20 07:00:15 +0530 |
---|---|---|
committer | Pradyun Gedam <pradyunsg@users.noreply.github.com> | 2020-10-27 19:32:35 +0530 |
commit | 95171c881fa8bc98b9dcd2f5c0c34cd7fce95904 (patch) | |
tree | 9e484802d5c4e3fd19206922adbc437d9f1cad8f | |
parent | 5bfd1db071c78c4bdcf2e80cc2142f1557d17d25 (diff) | |
download | pip-95171c881fa8bc98b9dcd2f5c0c34cd7fce95904.tar.gz |
Display messages when backtracking on a package
-rw-r--r-- | src/pip/_internal/resolution/resolvelib/reporter.py | 35 | ||||
-rw-r--r-- | src/pip/_internal/resolution/resolvelib/resolver.py | 5 | ||||
-rw-r--r-- | tests/functional/test_new_resolver.py | 45 |
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 |