diff --git a/news/6772.bugfix b/news/6772.bugfix new file mode 100644 index 000000000..b85e44c8a --- /dev/null +++ b/news/6772.bugfix @@ -0,0 +1,2 @@ +Fix a ``NoneType`` ``AttributeError`` when evaluating hashes and no hashes +are provided. diff --git a/src/pip/_internal/models/link.py b/src/pip/_internal/models/link.py index 01983e707..d42be28c4 100644 --- a/src/pip/_internal/models/link.py +++ b/src/pip/_internal/models/link.py @@ -200,11 +200,11 @@ class Link(KeyBasedCompareMixin): return self.hash_name is not None def is_hash_allowed(self, hashes): - # type: (Hashes) -> bool + # type: (Optional[Hashes]) -> bool """ Return True if the link has a hash and it is allowed. """ - if not self.has_hash: + if hashes is None or not self.has_hash: return False # Assert non-None so mypy knows self.hash_name and self.hash are str. assert self.hash_name is not None diff --git a/tests/unit/test_link.py b/tests/unit/test_link.py index a1d8d40a8..8a8182d39 100644 --- a/tests/unit/test_link.py +++ b/tests/unit/test_link.py @@ -117,3 +117,13 @@ class TestLink: } 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