def test_success(self, tmpdir): """Make sure no error is raised when at least one hash matches. Test check_against_path because it calls everything else. """ file = tmpdir / 'to_hash' file.write('hello') hashes = Hashes({ 'sha256': ['2cf24dba5fb0a30e26e83b2ac5b9e29e' '1b161e5c1fa7425e73043362938b9824'], 'sha224': ['wrongwrong'], 'md5': ['5d41402abc4b2a76b9719d911017c592']}) hashes.check_against_path(file)
def test_unknown_hash(self): """Hashes should raise InstallationError when it encounters an unknown hash.""" hashes = Hashes({'badbad': ['dummy']}) with pytest.raises(InstallationError): hashes.check_against_file(BytesIO(b'hello'))
def test_failure(self): """Hashes should raise HashMismatch when no hashes match.""" hashes = Hashes({'sha256': ['wrongwrong']}) with pytest.raises(HashMismatch): hashes.check_against_file(BytesIO(b'hello'))
def test_non_zero(self) -> None: """Test that truthiness tests tell whether any known-good hashes exist.""" assert Hashes({"sha256": ["dummy"]}) assert not Hashes() assert not Hashes({})
def test_equality(self) -> None: assert Hashes() == Hashes() assert Hashes({"sha256": ["abcd"]}) == Hashes({"sha256": ["abcd"]}) assert Hashes({"sha256": ["ab", "cd"]}) == Hashes({"sha256": ["cd", "ab"]})
def test_failure(self) -> None: """Hashes should raise HashMismatch when no hashes match.""" hashes = Hashes({"sha256": ["wrongwrong"]}) with pytest.raises(HashMismatch): hashes.check_against_file(BytesIO(b"hello"))
def test_unknown_hash(self) -> None: """Hashes should raise InstallationError when it encounters an unknown hash.""" hashes = Hashes({"badbad": ["dummy"]}) with pytest.raises(InstallationError): hashes.check_against_file(BytesIO(b"hello"))
def test_equality(self): assert Hashes() == Hashes() assert Hashes({'sha256': ['abcd']}) == Hashes({'sha256': ['abcd']}) assert Hashes({'sha256': ['ab', 'cd']}) == Hashes({'sha256': ['cd', 'ab']})
def test_hash(self): cache = {} cache[Hashes({'sha256': ['ab', 'cd']})] = 42 assert cache[Hashes({'sha256': ['ab', 'cd']})] == 42
def test_unknown_hash(self): """Hashes should raise InstallationError when it encounters an unknown hash.""" hashes = Hashes({'badbad': ['dummy']}) with pytest.raises(InstallationError): hashes.check_against_file(BytesIO(b'hello'))
def test_non_zero(self): """Test that truthiness tests tell whether any known-good hashes exist.""" assert Hashes({'sha256': 'dummy'}) assert not Hashes() assert not Hashes({})
def test_failure(self): """Hashes should raise HashMismatch when no hashes match.""" hashes = Hashes({'sha256': ['wrongwrong']}) with pytest.raises(HashMismatch): hashes.check_against_file(BytesIO(b'hello'))
def test_is_hash_allowed(self, hash_name, hex_digest, expected): hashes_data = { 'sha512': [128 * 'a', 128 * 'b'], } hashes = Hashes(hashes_data) assert hashes.is_hash_allowed(hash_name, hex_digest) == expected
class TestLink: @pytest.mark.parametrize('url, expected', [ ( 'https://*****:*****@example.com/path/page.html', '<Link https://user:****@example.com/path/page.html>', ), ]) def test_repr(self, url, expected): link = Link(url) assert repr(link) == expected @pytest.mark.parametrize('url, expected', [ ('http://yo/wheel.whl', 'wheel.whl'), ('http://yo/wheel', 'wheel'), ('https://example.com/path/page.html', 'page.html'), # Test a quoted character. ('https://example.com/path/page%231.html', 'page#1.html'), ( 'http://yo/myproject-1.0%2Bfoobar.0-py2.py3-none-any.whl', 'myproject-1.0+foobar.0-py2.py3-none-any.whl', ), # Test a path that ends in a slash. ('https://example.com/path/', 'path'), ('https://example.com/path//', 'path'), # Test a url with no filename. ('https://example.com/', 'example.com'), # Test a url with no filename and with auth information. ( 'https://*****:*****@example.com/', 'example.com', ), ]) def test_filename(self, url, expected): link = Link(url) assert link.filename == expected def test_splitext(self): assert ('wheel', '.whl') == Link('http://yo/wheel.whl').splitext() def test_no_ext(self): assert '' == Link('http://yo/wheel').ext def test_ext(self): assert '.whl' == Link('http://yo/wheel.whl').ext def test_ext_fragment(self): assert '.whl' == Link('http://yo/wheel.whl#frag').ext def test_ext_query(self): assert '.whl' == Link('http://yo/wheel.whl?a=b').ext def test_is_wheel(self): assert Link('http://yo/wheel.whl').is_wheel def test_is_wheel_false(self): assert not Link('http://yo/not_a_wheel').is_wheel def test_fragments(self): url = 'git+https://example.com/package#egg=eggname' assert 'eggname' == Link(url).egg_fragment assert None is Link(url).subdirectory_fragment url = 'git+https://example.com/package#egg=eggname&subdirectory=subdir' assert 'eggname' == Link(url).egg_fragment assert 'subdir' == Link(url).subdirectory_fragment url = 'git+https://example.com/package#subdirectory=subdir&egg=eggname' assert 'eggname' == Link(url).egg_fragment assert 'subdir' == Link(url).subdirectory_fragment @pytest.mark.parametrize('yanked_reason, expected', [ (None, False), ('', True), ('there was a mistake', True), ]) def test_is_yanked(self, yanked_reason, expected): link = Link( 'https://example.com/wheel.whl', yanked_reason=yanked_reason, ) assert link.is_yanked == expected @pytest.mark.parametrize('hash_name, hex_digest, expected', [ # Test a value that matches but with the wrong hash_name. ('sha384', 128 * 'a', False), # Test matching values, including values other than the first. ('sha512', 128 * 'a', True), ('sha512', 128 * 'b', True), # Test a matching hash_name with a value that doesn't match. ('sha512', 128 * 'c', False), # Test a link without a hash value. ('sha512', '', False), ]) def test_is_hash_allowed(self, hash_name, hex_digest, expected): url = ( 'https://example.com/wheel.whl#{hash_name}={hex_digest}'.format( hash_name=hash_name, hex_digest=hex_digest, ) ) link = Link(url) hashes_data = { 'sha512': [128 * 'a', 128 * 'b'], } hashes = Hashes(hashes_data) assert link.is_hash_allowed(hashes) == expected def test_is_hash_allowed__no_hash(self): link = Link('https://example.com/wheel.whl') hashes_data = { 'sha512': [128 * 'a'], } hashes = Hashes(hashes_data) assert not link.is_hash_allowed(hashes) @pytest.mark.parametrize('hashes, expected', [ (None, False), # Also test a success case to show the test is correct. (Hashes({'sha512': [128 * 'a']}), True), ]) def test_is_hash_allowed__none_hashes(self, hashes, expected): url = 'https://example.com/wheel.whl#sha512={}'.format(128 * 'a') link = Link(url) assert link.is_hash_allowed(hashes) == expected
def _iter_found_candidates( self, ireqs, # type: Sequence[InstallRequirement] specifier, # type: SpecifierSet ): # type: (...) -> Iterable[Candidate] if not ireqs: return () # The InstallRequirement implementation requires us to give it a # "template". Here we just choose the first requirement to represent # all of them. # Hopefully the Project model can correct this mismatch in the future. template = ireqs[0] name = canonicalize_name(template.req.name) hashes = Hashes() extras = frozenset() # type: FrozenSet[str] for ireq in ireqs: specifier &= ireq.req.specifier hashes |= ireq.hashes(trust_internet=False) extras |= frozenset(ireq.extras) # We use this to ensure that we only yield a single candidate for # each version (the finder's preferred one for that version). The # requirement needs to return only one candidate per version, so we # implement that logic here so that requirements using this helper # don't all have to do the same thing later. candidates = collections.OrderedDict() # type: VersionCandidates # Get the installed version, if it matches, unless the user # specified `--force-reinstall`, when we want the version from # the index instead. installed_version = None installed_candidate = None if not self._force_reinstall and name in self._installed_dists: installed_dist = self._installed_dists[name] installed_version = installed_dist.parsed_version if specifier.contains(installed_version, prereleases=True): installed_candidate = self._make_candidate_from_dist( dist=installed_dist, extras=extras, template=template, ) found = self._finder.find_best_candidate( project_name=name, specifier=specifier, hashes=hashes, ) for ican in found.iter_applicable(): if ican.version == installed_version and installed_candidate: candidate = installed_candidate else: candidate = self._make_candidate_from_link( link=ican.link, extras=extras, template=template, name=name, version=ican.version, ) candidates[ican.version] = candidate # Yield the installed version even if it is not found on the index. if installed_version and installed_candidate: candidates[installed_version] = installed_candidate return six.itervalues(candidates)
def empty(cls): # type: () -> Constraint return Constraint(SpecifierSet(), Hashes(), frozenset())