Skip to content

Commit

Permalink
Merge pull request #6719 from cjerdonek/candidate-evaluator-specifier
Browse files Browse the repository at this point in the history
Pass the specifier to CandidateEvaluator via create() instead of get_applicable_candidates()
  • Loading branch information
cjerdonek authored Jul 17, 2019
2 parents 90fa087 + 2de3804 commit ee5716c
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 27 deletions.
30 changes: 15 additions & 15 deletions src/pip/_internal/index.py
Original file line number Diff line number Diff line change
Expand Up @@ -550,7 +550,8 @@ def create(
target_python=None, # type: Optional[TargetPython]
prefer_binary=False, # type: bool
allow_all_prereleases=False, # type: bool
hashes=None, # type: Optional[Hashes]
specifier=None, # type: Optional[specifiers.BaseSpecifier]
hashes=None, # type: Optional[Hashes]
):
# type: (...) -> CandidateEvaluator
"""Create a CandidateEvaluator object.
Expand All @@ -562,12 +563,15 @@ def create(
"""
if target_python is None:
target_python = TargetPython()
if specifier is None:
specifier = specifiers.SpecifierSet()

supported_tags = target_python.get_tags()

return cls(
project_name=project_name,
supported_tags=supported_tags,
specifier=specifier,
prefer_binary=prefer_binary,
allow_all_prereleases=allow_all_prereleases,
hashes=hashes,
Expand All @@ -577,6 +581,7 @@ def __init__(
self,
project_name, # type: str
supported_tags, # type: List[Pep425Tag]
specifier, # type: specifiers.BaseSpecifier
prefer_binary=False, # type: bool
allow_all_prereleases=False, # type: bool
hashes=None, # type: Optional[Hashes]
Expand All @@ -590,19 +595,20 @@ def __init__(
self._hashes = hashes
self._prefer_binary = prefer_binary
self._project_name = project_name
self._specifier = specifier
self._supported_tags = supported_tags

def get_applicable_candidates(
self,
candidates, # type: List[InstallationCandidate]
specifier, # type: specifiers.BaseSpecifier
):
# type: (...) -> List[InstallationCandidate]
"""
Return the applicable candidates from a list of candidates.
"""
# Using None infers from the specifier instead.
allow_prereleases = self._allow_all_prereleases or None
specifier = self._specifier
versions = {
str(v) for v in specifier.filter(
# We turn the version object into a str here because otherwise
Expand Down Expand Up @@ -631,7 +637,6 @@ def get_applicable_candidates(
def make_found_candidates(
self,
candidates, # type: List[InstallationCandidate]
specifier=None, # type: Optional[specifiers.BaseSpecifier]
):
# type: (...) -> FoundCandidates
"""
Expand All @@ -641,13 +646,7 @@ def make_found_candidates(
(e.g. `packaging.specifiers.SpecifierSet`) to filter applicable
versions.
"""
if specifier is None:
specifier = specifiers.SpecifierSet()

applicable_candidates = self.get_applicable_candidates(
candidates=candidates,
specifier=specifier,
)
applicable_candidates = self.get_applicable_candidates(candidates)

return FoundCandidates(
candidates,
Expand Down Expand Up @@ -1149,8 +1148,9 @@ def find_all_candidates(self, project_name):

def make_candidate_evaluator(
self,
project_name, # type: str
hashes=None, # type: Optional[Hashes]
project_name, # type: str
specifier=None, # type: Optional[specifiers.BaseSpecifier]
hashes=None, # type: Optional[Hashes]
):
# type: (...) -> CandidateEvaluator
"""Create a CandidateEvaluator object to use.
Expand All @@ -1161,6 +1161,7 @@ def make_candidate_evaluator(
target_python=self._target_python,
prefer_binary=candidate_prefs.prefer_binary,
allow_all_prereleases=candidate_prefs.allow_all_prereleases,
specifier=specifier,
hashes=hashes,
)

Expand All @@ -1182,11 +1183,10 @@ def find_candidates(
candidates = self.find_all_candidates(project_name)
candidate_evaluator = self.make_candidate_evaluator(
project_name=project_name,
specifier=specifier,
hashes=hashes,
)
return candidate_evaluator.make_found_candidates(
candidates, specifier=specifier,
)
return candidate_evaluator.make_found_candidates(candidates)

def find_requirement(self, req, upgrade):
# type: (InstallRequirement, bool) -> Optional[Link]
Expand Down
6 changes: 5 additions & 1 deletion tests/unit/test_finder.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import pytest
from mock import Mock, patch
from pip._vendor.packaging.specifiers import SpecifierSet
from pkg_resources import parse_version

import pip._internal.pep425tags
Expand Down Expand Up @@ -216,7 +217,10 @@ def test_link_sorting(self):
('pyT', 'TEST', 'any'),
('pyT', 'none', 'any'),
]
evaluator = CandidateEvaluator('my-project', supported_tags=valid_tags)
specifier = SpecifierSet()
evaluator = CandidateEvaluator(
'my-project', supported_tags=valid_tags, specifier=specifier,
)
sort_key = evaluator._sort_key
results = sorted(links, key=sort_key, reverse=True)
results2 = sorted(reversed(links), key=sort_key, reverse=True)
Expand Down
40 changes: 29 additions & 11 deletions tests/unit/test_index.py
Original file line number Diff line number Diff line change
Expand Up @@ -299,14 +299,17 @@ class TestCandidateEvaluator:
def test_create(self, allow_all_prereleases, prefer_binary):
target_python = TargetPython()
target_python._valid_tags = [('py36', 'none', 'any')]
specifier = SpecifierSet()
evaluator = CandidateEvaluator.create(
project_name='my-project',
target_python=target_python,
allow_all_prereleases=allow_all_prereleases,
prefer_binary=prefer_binary,
specifier=specifier,
)
assert evaluator._allow_all_prereleases == allow_all_prereleases
assert evaluator._prefer_binary == prefer_binary
assert evaluator._specifier is specifier
assert evaluator._supported_tags == [('py36', 'none', 'any')]

def test_create__target_python_none(self):
Expand All @@ -317,16 +320,25 @@ def test_create__target_python_none(self):
expected_tags = get_supported()
assert evaluator._supported_tags == expected_tags

def test_create__specifier_none(self):
"""
Test passing specifier=None.
"""
evaluator = CandidateEvaluator.create('my-project')
expected_specifier = SpecifierSet()
assert evaluator._specifier == expected_specifier

def test_get_applicable_candidates(self):
specifier = SpecifierSet('<= 1.11')
versions = ['1.10', '1.11', '1.12']
candidates = [
make_mock_candidate(version) for version in versions
]
evaluator = CandidateEvaluator.create('my-project')
actual = evaluator.get_applicable_candidates(
candidates, specifier=specifier,
evaluator = CandidateEvaluator.create(
'my-project',
specifier=specifier,
)
actual = evaluator.get_applicable_candidates(candidates)
expected_applicable = candidates[:2]
assert [str(c.version) for c in expected_applicable] == [
'1.10',
Expand All @@ -347,7 +359,6 @@ def test_get_applicable_candidates__hashes(
"""
Test a non-None hashes value.
"""
# specifier = SpecifierSet('<= 1.1')
candidates = [
make_mock_candidate('1.0'),
make_mock_candidate('1.1', hex_digest=(64 * 'a')),
Expand All @@ -357,10 +368,12 @@ def test_get_applicable_candidates__hashes(
'sha256': [64 * 'b'],
}
hashes = Hashes(hashes_data)
evaluator = CandidateEvaluator.create('my-project', hashes=hashes)
actual = evaluator.get_applicable_candidates(
candidates, specifier=specifier,
evaluator = CandidateEvaluator.create(
'my-project',
specifier=specifier,
hashes=hashes,
)
actual = evaluator.get_applicable_candidates(candidates)
actual_versions = [str(c.version) for c in actual]
assert actual_versions == expected_versions

Expand All @@ -370,10 +383,11 @@ def test_make_found_candidates(self):
candidates = [
make_mock_candidate(version) for version in versions
]
evaluator = CandidateEvaluator.create('my-project')
found_candidates = evaluator.make_found_candidates(
candidates, specifier=specifier,
evaluator = CandidateEvaluator.create(
'my-project',
specifier=specifier,
)
found_candidates = evaluator.make_found_candidates(candidates)

assert found_candidates._candidates == candidates
assert found_candidates._evaluator is evaluator
Expand Down Expand Up @@ -776,15 +790,19 @@ def test_make_candidate_evaluator(
candidate_prefs=candidate_prefs,
)

specifier = SpecifierSet()
# Pass hashes to check that _hashes is set.
hashes = Hashes({'sha256': [64 * 'a']})
evaluator = finder.make_candidate_evaluator(
'my-project', hashes=hashes,
'my-project',
specifier=specifier,
hashes=hashes,
)
assert evaluator._allow_all_prereleases == allow_all_prereleases
assert evaluator._hashes == hashes
assert evaluator._prefer_binary == prefer_binary
assert evaluator._project_name == 'my-project'
assert evaluator._specifier is specifier
assert evaluator._supported_tags == [('py36', 'none', 'any')]


Expand Down

0 comments on commit ee5716c

Please sign in to comment.