|
21 | 21 | from pip._internal.wheel import InvalidWheelFilename, Wheel
|
22 | 22 |
|
23 | 23 | if MYPY_CHECK_RUNNING:
|
24 |
| - from typing import Optional, Set, List, Any |
| 24 | + from typing import Optional, Set, List, Any, Dict |
25 | 25 | from pip._internal.models.format_control import FormatControl
|
26 | 26 | from pip._internal.pep425tags import Pep425Tag
|
27 | 27 |
|
28 | 28 | logger = logging.getLogger(__name__)
|
29 | 29 |
|
30 | 30 |
|
| 31 | +def _hash_dict(d): |
| 32 | + # type: (Dict[str, str]) -> str |
| 33 | + """Return a sha224 of a dictionary where keys and values are strings.""" |
| 34 | + h = hashlib.new('sha224') |
| 35 | + for k in sorted(d.keys()): |
| 36 | + h.update(k.encode()) |
| 37 | + h.update("=".encode()) |
| 38 | + h.update(d[k].encode()) |
| 39 | + h.update(b"\0") |
| 40 | + return h.hexdigest() |
| 41 | + |
| 42 | + |
31 | 43 | class Cache(object):
|
32 | 44 | """An abstract class - provides cache directories for data from links
|
33 | 45 |
|
@@ -57,32 +69,28 @@ def _get_cache_path_parts(self, link):
|
57 | 69 | # We want to generate an url to use as our cache key, we don't want to
|
58 | 70 | # just re-use the URL because it might have other items in the fragment
|
59 | 71 | # and we don't care about those.
|
60 |
| - key_parts = [link.url_without_fragment] |
| 72 | + key_parts = {"url": link.url_without_fragment} |
61 | 73 | if link.hash_name is not None and link.hash is not None:
|
62 |
| - key_parts.append("=".join([link.hash_name, link.hash])) |
| 74 | + key_parts[link.hash_name] = link.hash |
63 | 75 | if link.subdirectory_fragment:
|
64 |
| - key_parts.append( |
65 |
| - "=".join(["subdirectory", link.subdirectory_fragment]) |
66 |
| - ) |
67 |
| - key_url = "#".join(key_parts) |
| 76 | + key_parts["subdirectory"] = link.subdirectory_fragment |
68 | 77 |
|
69 | 78 | # Include interpreter name, major and minor version in cache key
|
70 | 79 | # to cope with ill-behaved sdists that build a different wheel
|
71 | 80 | # depending on the python version their setup.py is being run on,
|
72 | 81 | # and don't encode the difference in compatibility tags.
|
73 | 82 | # https://github.com/pypa/pip/issues/7296
|
74 |
| - key = "{}-{}.{} {}".format( |
| 83 | + key_parts["interpreter"] = "{}-{}.{}".format( |
75 | 84 | interpreter_name(),
|
76 | 85 | sys.version_info[0],
|
77 | 86 | sys.version_info[1],
|
78 |
| - key_url, |
79 | 87 | )
|
80 | 88 |
|
81 | 89 | # Encode our key url with sha224, we'll use this because it has similar
|
82 | 90 | # security properties to sha256, but with a shorter total output (and
|
83 | 91 | # thus less secure). However the differences don't make a lot of
|
84 | 92 | # difference for our use case here.
|
85 |
| - hashed = hashlib.sha224(key.encode()).hexdigest() |
| 93 | + hashed = _hash_dict(key_parts) |
86 | 94 |
|
87 | 95 | # We want to nest the directories some to prevent having a ton of top
|
88 | 96 | # level directories where we might run out of sub directories on some
|
|
0 commit comments