diff --git a/src/pip/_internal/resolution/resolvelib/factory.py b/src/pip/_internal/resolution/resolvelib/factory.py index 145bdbf71a1..09437cffa30 100644 --- a/src/pip/_internal/resolution/resolvelib/factory.py +++ b/src/pip/_internal/resolution/resolvelib/factory.py @@ -742,7 +742,7 @@ def get_installation_error( # The simplest case is when we have *one* cause that can't be # satisfied. We just report that case. if len(e.causes) == 1: - req, parent = e.causes[0] + req, parent = next(iter(e.causes)) if req.name not in constraints: return self._report_single_requirement_conflict(req, parent) diff --git a/src/pip/_internal/resolution/resolvelib/reporter.py b/src/pip/_internal/resolution/resolvelib/reporter.py index 0594569d850..587b15d1ca1 100644 --- a/src/pip/_internal/resolution/resolvelib/reporter.py +++ b/src/pip/_internal/resolution/resolvelib/reporter.py @@ -1,6 +1,6 @@ from collections import defaultdict from logging import getLogger -from typing import Any, DefaultDict +from typing import Any, DefaultDict, Optional from pip._vendor.resolvelib.reporters import BaseReporter @@ -9,7 +9,7 @@ logger = getLogger(__name__) -class PipReporter(BaseReporter): +class PipReporter(BaseReporter[Requirement, Candidate, Any]): def __init__(self) -> None: self.reject_count_by_package: DefaultDict[str, int] = defaultdict(int) @@ -55,7 +55,7 @@ def rejecting_candidate(self, criterion: Any, candidate: Candidate) -> None: logger.debug(msg) -class PipDebuggingReporter(BaseReporter): +class PipDebuggingReporter(BaseReporter[Requirement, Candidate, Any]): """A reporter that does an info log for every event it sees.""" def starting(self) -> None: @@ -71,7 +71,9 @@ def ending_round(self, index: int, state: Any) -> None: def ending(self, state: Any) -> None: logger.info("Reporter.ending(%r)", state) - def adding_requirement(self, requirement: Requirement, parent: Candidate) -> None: + def adding_requirement( + self, requirement: Requirement, parent: Optional[Candidate] + ) -> None: logger.info("Reporter.adding_requirement(%r, %r)", requirement, parent) def rejecting_candidate(self, criterion: Any, candidate: Candidate) -> None: diff --git a/src/pip/_internal/resolution/resolvelib/resolver.py b/src/pip/_internal/resolution/resolvelib/resolver.py index c12beef0b2a..07dcb766b2c 100644 --- a/src/pip/_internal/resolution/resolvelib/resolver.py +++ b/src/pip/_internal/resolution/resolvelib/resolver.py @@ -2,7 +2,7 @@ import functools import logging import os -from typing import TYPE_CHECKING, Dict, List, Optional, Set, Tuple, cast +from typing import TYPE_CHECKING, Any, Dict, List, Optional, Set, Tuple, cast from pip._vendor.packaging.utils import canonicalize_name from pip._vendor.resolvelib import BaseReporter, ResolutionImpossible @@ -82,7 +82,7 @@ def resolve( user_requested=collected.user_requested, ) if "PIP_RESOLVER_DEBUG" in os.environ: - reporter: BaseReporter = PipDebuggingReporter() + reporter: BaseReporter[Requirement, Candidate, Any] = PipDebuggingReporter() else: reporter = PipReporter() resolver: RLResolver[Requirement, Candidate, str] = RLResolver( diff --git a/tests/unit/resolution_resolvelib/test_provider.py b/tests/unit/resolution_resolvelib/test_provider.py index 5f30e2bc1dd..e3d43f6a3ef 100644 --- a/tests/unit/resolution_resolvelib/test_provider.py +++ b/tests/unit/resolution_resolvelib/test_provider.py @@ -5,6 +5,7 @@ from pip._internal.models.candidate import InstallationCandidate from pip._internal.models.link import Link from pip._internal.req.constructors import install_req_from_req_string +from pip._internal.resolution.resolvelib.base import Candidate from pip._internal.resolution.resolvelib.factory import Factory from pip._internal.resolution.resolvelib.provider import PipProvider from pip._internal.resolution.resolvelib.requirements import SpecifierRequirement @@ -14,13 +15,13 @@ def build_requirement_information( - name: str, parent: Optional[InstallationCandidate] + name: str, parent: Optional[Candidate] ) -> List["PreferenceInformation"]: install_requirement = install_req_from_req_string(name) # RequirementInformation is typed as a tuple, but it is a namedtupled. # https://github.com/sarugaku/resolvelib/blob/7bc025aa2a4e979597c438ad7b17d2e8a08a364e/src/resolvelib/resolvers.pyi#L20-L22 requirement_information: PreferenceInformation = RequirementInformation( - requirement=SpecifierRequirement(install_requirement), # type: ignore[call-arg] + requirement=SpecifierRequirement(install_requirement), parent=parent, ) return [requirement_information] @@ -60,7 +61,8 @@ def test_provider_known_depths(factory: Factory) -> None: transitive_requirement_name = "my-transitive-package" transitive_package_information = build_requirement_information( - name=transitive_requirement_name, parent=root_package_candidate + name=transitive_requirement_name, + parent=root_package_candidate, # type: ignore ) provider.get_preference( identifier=transitive_requirement_name,