From ffe553638c035292e17657cbacbfb48e189a9221 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Thu, 19 Mar 2020 10:53:15 +0000 Subject: [PATCH] Address review requirements --- .../resolution/resolvelib/candidates.py | 18 +++++++++++++++--- .../resolution/resolvelib/provider.py | 8 ++++++++ .../resolution/resolvelib/requirements.py | 1 + 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/pip/_internal/resolution/resolvelib/candidates.py b/src/pip/_internal/resolution/resolvelib/candidates.py index a8e1aa903..08eff0ddf 100644 --- a/src/pip/_internal/resolution/resolvelib/candidates.py +++ b/src/pip/_internal/resolution/resolvelib/candidates.py @@ -7,7 +7,7 @@ from pip._internal.utils.typing import MYPY_CHECK_RUNNING from .base import Candidate if MYPY_CHECK_RUNNING: - from typing import Dict, Optional, Sequence + from typing import Any, Dict, Optional, Sequence from pip._internal.models.link import Link from pip._internal.operations.prepare import RequirementPreparer @@ -17,7 +17,6 @@ if MYPY_CHECK_RUNNING: from pip._vendor.pkg_resources import Distribution -# Dummy to make lint pass _CANDIDATE_CACHE = {} # type: Dict[Link, Candidate] @@ -74,9 +73,21 @@ class LinkCandidate(Candidate): self._version = None # type: Optional[_BaseVersion] self._dist = None # type: Optional[Distribution] + def __eq__(self, other): + # type: (Any) -> bool + if isinstance(other, self.__class__): + return self.link == other.link + return False + + # Needed for Python 2, which does not implement this by default + def __ne__(self, other): + # type: (Any) -> bool + return not self.__eq__(other) + @property def name(self): # type: () -> str + """The normalised name of the project the candidate refers to""" if self._name is None: self._name = canonicalize_name(self.dist.project_name) return self._name @@ -101,7 +112,8 @@ class LinkCandidate(Candidate): # These should be "proper" errors, not just asserts, as they # can result from user errors like a requirement "foo @ URL" # when the project at URL has a name of "bar" in its metadata. - assert self._name is None or self._name == self._dist.project_name + assert (self._name is None or + self._name == canonicalize_name(self._dist.project_name)) assert (self._version is None or self._version == self.dist.parsed_version) return self._dist diff --git a/src/pip/_internal/resolution/resolvelib/provider.py b/src/pip/_internal/resolution/resolvelib/provider.py index 21c3ecbb6..981646ea9 100644 --- a/src/pip/_internal/resolution/resolvelib/provider.py +++ b/src/pip/_internal/resolution/resolvelib/provider.py @@ -38,6 +38,14 @@ class PipProvider(AbstractProvider): def get_install_requirement(self, c): # type: (Candidate) -> InstallRequirement + + # The base Candidate class does not have an _ireq attribute, so we + # fetch it dynamically here, to satisfy mypy. In practice, though, we + # only ever deal with LinkedCandidate objects at the moment, which do + # have an _ireq attribute. When we have a candidate type for installed + # requirements we should probably review this. + # + # TODO: Longer term, make a proper interface for this on the candidate. return getattr(c, "_ireq", None) def identify(self, dependency): diff --git a/src/pip/_internal/resolution/resolvelib/requirements.py b/src/pip/_internal/resolution/resolvelib/requirements.py index d5965e3e1..4adc8a09a 100644 --- a/src/pip/_internal/resolution/resolvelib/requirements.py +++ b/src/pip/_internal/resolution/resolvelib/requirements.py @@ -48,6 +48,7 @@ class ExplicitRequirement(Requirement): @property def name(self): # type: () -> str + # No need to canonicalise - the candidate did this return self.candidate.name def find_matches(self):