Pass the hashes when creating the CandidateEvaluator.

This commit is contained in:
Chris Jerdonek 2019-07-10 20:35:30 -07:00
parent e80fc233ff
commit 9ddc89a21d
2 changed files with 52 additions and 6 deletions

View File

@ -513,6 +513,7 @@ class CandidateEvaluator(object):
target_python=None, # type: Optional[TargetPython]
prefer_binary=False, # type: bool
allow_all_prereleases=False, # type: bool
hashes=None, # type: Optional[Hashes]
):
# type: (...) -> CandidateEvaluator
"""Create a CandidateEvaluator object.
@ -520,6 +521,7 @@ class CandidateEvaluator(object):
:param target_python: The target Python interpreter to use when
checking compatibility. If None (the default), a TargetPython
object will be constructed from the running Python.
:param hashes: An optional collection of allowed hashes.
"""
if target_python is None:
target_python = TargetPython()
@ -530,6 +532,7 @@ class CandidateEvaluator(object):
supported_tags=supported_tags,
prefer_binary=prefer_binary,
allow_all_prereleases=allow_all_prereleases,
hashes=hashes,
)
def __init__(
@ -537,6 +540,7 @@ class CandidateEvaluator(object):
supported_tags, # type: List[Pep425Tag]
prefer_binary=False, # type: bool
allow_all_prereleases=False, # type: bool
hashes=None, # type: Optional[Hashes]
):
# type: (...) -> None
"""
@ -544,6 +548,7 @@ class CandidateEvaluator(object):
Python in order of preference (most preferred first).
"""
self._allow_all_prereleases = allow_all_prereleases
self._hashes = hashes
self._prefer_binary = prefer_binary
self._supported_tags = supported_tags
@ -576,7 +581,10 @@ class CandidateEvaluator(object):
applicable_candidates = [
c for c in candidates if str(c.version) in versions
]
return applicable_candidates
return filter_unallowed_hashes(
candidates=applicable_candidates, hashes=self._hashes,
)
def make_found_candidates(
self,
@ -1089,8 +1097,8 @@ class PackageFinder(object):
# This is an intentional priority ordering
return file_versions + find_links_versions + page_versions
def make_candidate_evaluator(self):
# type: (...) -> CandidateEvaluator
def make_candidate_evaluator(self, hashes=None):
# type: (Optional[Hashes]) -> CandidateEvaluator
"""Create a CandidateEvaluator object to use.
"""
candidate_prefs = self._candidate_prefs
@ -1098,12 +1106,14 @@ class PackageFinder(object):
target_python=self._target_python,
prefer_binary=candidate_prefs.prefer_binary,
allow_all_prereleases=candidate_prefs.allow_all_prereleases,
hashes=hashes,
)
def find_candidates(
self,
project_name, # type: str
specifier=None, # type: Optional[specifiers.BaseSpecifier]
hashes=None, # type: Optional[Hashes]
):
# type: (...) -> FoundCandidates
"""Find matches for the given project and specifier.
@ -1115,7 +1125,7 @@ class PackageFinder(object):
:return: A `FoundCandidates` instance.
"""
candidates = self.find_all_candidates(project_name)
candidate_evaluator = self.make_candidate_evaluator()
candidate_evaluator = self.make_candidate_evaluator(hashes=hashes)
return candidate_evaluator.make_found_candidates(
candidates, specifier=specifier,
)
@ -1128,7 +1138,10 @@ class PackageFinder(object):
Returns a Link if found,
Raises DistributionNotFound or BestVersionAlreadyInstalled otherwise
"""
candidates = self.find_candidates(req.name, req.specifier)
hashes = req.hashes(trust_internet=False)
candidates = self.find_candidates(
req.name, specifier=req.specifier, hashes=hashes,
)
best_candidate = candidates.get_best()
installed_version = None # type: Optional[_BaseVersion]

View File

@ -252,6 +252,36 @@ class TestCandidateEvaluator:
]
assert actual == expected_applicable
@pytest.mark.parametrize('specifier, expected_versions', [
# Test no version constraint.
(SpecifierSet(), ['1.0', '1.2']),
# Test a version constraint that excludes the candidate whose
# hash matches. Then the non-allowed hash is a candidate.
(SpecifierSet('<= 1.1'), ['1.0', '1.1']),
])
def test_get_applicable_candidates__hashes(
self, specifier, expected_versions,
):
"""
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')),
make_mock_candidate('1.2', hex_digest=(64 * 'b')),
]
hashes_data = {
'sha256': [64 * 'b'],
}
hashes = Hashes(hashes_data)
evaluator = CandidateEvaluator.create(hashes=hashes)
actual = evaluator.get_applicable_candidates(
candidates, specifier=specifier,
)
actual_versions = [str(c.version) for c in actual]
assert actual_versions == expected_versions
def test_make_found_candidates(self):
specifier = SpecifierSet('<= 1.11')
versions = ['1.10', '1.11', '1.12']
@ -644,8 +674,11 @@ class TestPackageFinder:
candidate_prefs=candidate_prefs,
)
evaluator = finder.make_candidate_evaluator()
# Pass hashes to check that _hashes is set.
hashes = Hashes({'sha256': [64 * 'a']})
evaluator = finder.make_candidate_evaluator(hashes=hashes)
assert evaluator._allow_all_prereleases == allow_all_prereleases
assert evaluator._hashes == hashes
assert evaluator._prefer_binary == prefer_binary
assert evaluator._supported_tags == [('py36', 'none', 'any')]