Skip to content

Commit f3747bf

Browse files
committed
Restore pre 22.3 wheel cache pathing
Prior to bad03ef wheel cache paths incorporated source material hashes in their paths. This commit which ended up in 22.3 stopped including that information. This is problematic for two reasons. First our cache is no longer encoding data integrity information that was previously intentionally included. Second it means anyone upgrading from < 22.3 to 22.3 will have orphaned wheel cache entries. The fix here is to update the Link object to set Link.link_hash in the Link.from_json method. Otherwise the hash information is simply missing. This will cause anyone upgrading from 22.3 to newer to have orphaned wheels, but that seems worthwile considering 22.3 hasn't been around as long as the previous implementation and we get stronger data integrity controls out of it. This fixes pypa#11527
1 parent ff207cf commit f3747bf

File tree

3 files changed

+51
-1
lines changed

3 files changed

+51
-1
lines changed

news/11527.bugfix.rst

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
This change restores 22.2.x wheel cache behavior to pip allowing the
2+
cache to find existing entries.

src/pip/_internal/models/link.py

+6
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,11 @@ def from_json(
248248
yanked_reason = file_data.get("yanked")
249249
dist_info_metadata = file_data.get("dist-info-metadata")
250250
hashes = file_data.get("hashes", {})
251+
link_hash = None
252+
if hashes:
253+
for hash_name in _SUPPORTED_HASHES:
254+
if hash_name in hashes:
255+
link_hash = LinkHash(name=hash_name, value=hashes[hash_name])
251256

252257
# The Link.yanked_reason expects an empty string instead of a boolean.
253258
if yanked_reason and not isinstance(yanked_reason, str):
@@ -262,6 +267,7 @@ def from_json(
262267
requires_python=pyrequire,
263268
yanked_reason=yanked_reason,
264269
hashes=hashes,
270+
link_hash=link_hash,
265271
dist_info_metadata=dist_info_metadata,
266272
)
267273

tests/unit/test_cache.py

+43-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import os
22
from pathlib import Path
33

4-
from pip._vendor.packaging.tags import Tag
4+
from pip._vendor.packaging.tags import Tag, interpreter_name, interpreter_version
55

66
from pip._internal.cache import WheelCache, _hash_dict
77
from pip._internal.models.format_control import FormatControl
@@ -52,6 +52,48 @@ def test_cache_hash() -> None:
5252
assert h == "f83b32dfa27a426dec08c21bf006065dd003d0aac78e7fc493d9014d"
5353

5454

55+
def test_link_to_cache(tmpdir: Path) -> None:
56+
"""
57+
Test that Link.from_json() produces Links with consistent cache
58+
locations
59+
"""
60+
wc = WheelCache(os.fspath(tmpdir), FormatControl())
61+
# Define our expectations for stable cache path.
62+
i_name = interpreter_name()
63+
i_version = interpreter_version()
64+
key_parts = {
65+
"url": "https://files.pythonhosted.org/packages/a6/91/"
66+
"86a6eac449ddfae239e93ffc1918cf33fd9bab35c04d1e963b311e347a73/"
67+
"netifaces-0.11.0.tar.gz",
68+
"sha256": "043a79146eb2907edf439899f262b3dfe41717d34124298ed281139a8b93ca32",
69+
"interpreter_name": i_name,
70+
"interpreter_version": i_version,
71+
}
72+
expected_hash = _hash_dict(key_parts)
73+
parts = [
74+
expected_hash[:2],
75+
expected_hash[2:4],
76+
expected_hash[4:6],
77+
expected_hash[6:],
78+
]
79+
pathed_hash = os.path.join(*parts)
80+
# Check working from a Link produces the same result.
81+
file_data = {
82+
"filename": "netifaces-0.11.0.tar.gz",
83+
"hashes": {
84+
"sha256": key_parts["sha256"],
85+
},
86+
"requires-python": "",
87+
"url": key_parts["url"],
88+
"yanked": False,
89+
}
90+
page_url = "https://pypi.org/simple/netifaces/"
91+
link = Link.from_json(file_data=file_data, page_url=page_url)
92+
assert link
93+
path = wc.get_path_for_link(link)
94+
assert pathed_hash in path
95+
96+
5597
def test_get_cache_entry(tmpdir: Path) -> None:
5698
wc = WheelCache(os.fspath(tmpdir), FormatControl())
5799
persi_link = Link("https://g.c/o/r/persi")

0 commit comments

Comments
 (0)