-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Support wheel cache when using --require-hashes #11897
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
8e2205d
40cd79d
0e2a0db
a1af13c
f86ba46
ff8c8e3
a6ef648
caafe6e
bd746e3
4beca6b
efe2d27
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Support wheel cache when using ``--require-hashes``. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -179,7 +179,10 @@ def unpack_url( | |
|
||
|
||
def _check_download_dir( | ||
link: Link, download_dir: str, hashes: Optional[Hashes] | ||
link: Link, | ||
download_dir: str, | ||
hashes: Optional[Hashes], | ||
warn_on_hash_mismatch: bool = True, | ||
) -> Optional[str]: | ||
"""Check download_dir for previously downloaded file with correct hash | ||
If a correct file is found return its path else None | ||
|
@@ -195,10 +198,11 @@ def _check_download_dir( | |
try: | ||
hashes.check_against_path(download_path) | ||
except HashMismatch: | ||
logger.warning( | ||
"Previously-downloaded file %s has bad hash. Re-downloading.", | ||
download_path, | ||
) | ||
if warn_on_hash_mismatch: | ||
logger.warning( | ||
"Previously-downloaded file %s has bad hash. Re-downloading.", | ||
download_path, | ||
) | ||
os.unlink(download_path) | ||
return None | ||
return download_path | ||
|
@@ -263,7 +267,7 @@ def __init__( | |
|
||
def _log_preparing_link(self, req: InstallRequirement) -> None: | ||
"""Provide context for the requirement being prepared.""" | ||
if req.link.is_file and not req.original_link_is_in_wheel_cache: | ||
if req.link.is_file and not req.is_wheel_from_cache: | ||
message = "Processing %s" | ||
information = str(display_path(req.link.file_path)) | ||
else: | ||
|
@@ -284,7 +288,7 @@ def _log_preparing_link(self, req: InstallRequirement) -> None: | |
self._previous_requirement_header = (message, information) | ||
logger.info(message, information) | ||
|
||
if req.original_link_is_in_wheel_cache: | ||
if req.is_wheel_from_cache: | ||
with indent_log(): | ||
logger.info("Using cached %s", req.link.filename) | ||
|
||
|
@@ -485,7 +489,18 @@ def prepare_linked_requirement( | |
file_path = None | ||
if self.download_dir is not None and req.link.is_wheel: | ||
hashes = self._get_linked_req_hashes(req) | ||
file_path = _check_download_dir(req.link, self.download_dir, hashes) | ||
file_path = _check_download_dir( | ||
req.link, | ||
self.download_dir, | ||
hashes, | ||
# When a locally built wheel has been found in cache, we don't warn | ||
# about re-downloading when the already downloaded wheel hash does | ||
# not match. This is because the hash must be checked against the | ||
# original link, not the cached link. It that case the already | ||
# downloaded file will be removed and re-fetched from cache (which | ||
# implies a hash check against the cache entry's origin.json). | ||
warn_on_hash_mismatch=not req.is_wheel_from_cache, | ||
) | ||
|
||
if file_path is not None: | ||
# The file is already available, so mark it as downloaded | ||
|
@@ -536,9 +551,35 @@ def _prepare_linked_requirement( | |
assert req.link | ||
link = req.link | ||
|
||
self._ensure_link_req_src_dir(req, parallel_builds) | ||
hashes = self._get_linked_req_hashes(req) | ||
|
||
if hashes and req.is_wheel_from_cache: | ||
assert req.download_info is not None | ||
assert link.is_wheel | ||
assert link.is_file | ||
# We need to verify hashes, and we have found the requirement in the cache | ||
# of locally built wheels. | ||
if ( | ||
isinstance(req.download_info.info, ArchiveInfo) | ||
and req.download_info.info.hashes | ||
and hashes.has_one_of(req.download_info.info.hashes) | ||
): | ||
# At this point we know the requirement was built from a hashable source | ||
# artifact, and we verified that the cache entry's hash of the original | ||
# artifact matches one of the hashes we expect. We don't verify hashes | ||
# against the cached wheel, because the wheel is not the original. | ||
hashes = None | ||
else: | ||
logger.warning( | ||
"The hashes of the source archive found in cache entry " | ||
"don't match, ignoring cached built wheel " | ||
"and re-downloading source." | ||
) | ||
req.link = req.cached_wheel_source_link | ||
link = req.link | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, I'm afraid this part still needs some work. If req.download_info contains an invalid hash, it re-downloads an URL with an invalid hash fragment, which means we never get a good cache entry. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, I resolved this by adding a new |
||
|
||
self._ensure_link_req_src_dir(req, parallel_builds) | ||
|
||
if link.is_existing_dir(): | ||
local_file = None | ||
elif link.url not in self._downloaded: | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not some that needs to change, I’m just suddenly curious how peopel choose between positive and negative flags. Personally I’d probably choose to implement this as
suppress_hash_mismatch_warning=False
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this case I think I wanted to avoid a double negation and save half a brain cycle when reading the only condition using this flag.