Merge pull request #9720 from ThomasWaldmann/pure-hashing-wrapper-master
Some checks failed
Lint / lint (push) Has been cancelled
CI / lint (push) Has been cancelled
CI / security (push) Has been cancelled
CodeQL / Analyze (push) Has been cancelled
CI / asan_ubsan (push) Has been cancelled
CI / native_tests (push) Has been cancelled
CI / vm_tests (Haiku, false, haiku, r1beta5) (push) Has been cancelled
CI / vm_tests (NetBSD, false, netbsd, 10.1) (push) Has been cancelled
CI / vm_tests (OmniOS, false, omnios, r151056) (push) Has been cancelled
CI / vm_tests (OpenBSD, false, openbsd, 7.8) (push) Has been cancelled
CI / vm_tests (borg-freebsd-14-x86_64-gh, FreeBSD, true, freebsd, 14.3) (push) Has been cancelled
CI / windows_tests (push) Has been cancelled

add pure_hash option and tests for SHA256FileHashingWrapper, fixes #9704
This commit is contained in:
TW 2026-06-04 20:58:13 +02:00 committed by GitHub
commit 22bc6ee419
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 33 additions and 2 deletions

View file

@ -60,13 +60,14 @@ class FileHashingWrapper(FileLikeWrapper):
ALGORITHM: str = None
FACTORY: Callable = None
def __init__(self, backing_fd, write):
def __init__(self, backing_fd, write, *, pure_hash: bool = False):
super().__init__(backing_fd)
self.writing = write
self.hash = self.FACTORY()
self.pure_hash = pure_hash # if True, we don't hash the length of the file
def __exit__(self, exc_type, exc_val, exc_tb):
if exc_type is None:
if exc_type is None and not self.pure_hash:
self.hash_length()
super().__exit__(exc_type, exc_val, exc_tb)

View file

@ -1,6 +1,10 @@
import hashlib
import io
import pytest
from ...crypto.file_integrity import DetachedIntegrityCheckedFile, FileIntegrityError, IntegrityCheckedFile
from ...crypto.file_integrity import SHA256FileHashingWrapper
from ...platform import SyncFile
@ -147,3 +151,29 @@ class TestIntegrityCheckedFileWithSyncFile:
# verify the written data can be read back with integrity check
with IntegrityCheckedFile(path=path, write=False, integrity_data=integrity_data) as fd:
assert fd.read() == b"test data for integrity check"
class TestSHA256FileHashingWrapper:
def test_pure_hash_write(self):
bio = io.BytesIO()
data = b"hello world"
with SHA256FileHashingWrapper(bio, write=True, pure_hash=True) as wrapper:
wrapper.write(data)
assert bio.getvalue() == data
assert wrapper.hexdigest() == hashlib.sha256(data).hexdigest()
def test_pure_hash_read(self):
data = b"hello world"
bio = io.BytesIO(data)
with SHA256FileHashingWrapper(bio, write=False, pure_hash=True) as wrapper:
assert wrapper.read() == data
assert wrapper.hexdigest() == hashlib.sha256(data).hexdigest()
def test_impure_hash_write(self):
bio = io.BytesIO()
data = b"hello world"
with SHA256FileHashingWrapper(bio, write=True, pure_hash=False) as wrapper:
wrapper.write(data)
# pure_hash=False appends the file length ("11" in this case) at exit
expected_hash = hashlib.sha256(data + b"11").hexdigest()
assert wrapper.hexdigest() == expected_hash