Source code for simstack.util.file_hashing
import hashlib
from pathlib import Path
from typing import Union, BinaryIO
[docs]
def hash_file(
file_path: Union[str, Path], algorithm: str = "sha256", chunk_size: int = 8192
) -> str:
"""
Calculate hash of a file on disk.
Args:
file_path: Path to the file
algorithm: Hash algorithm (md5, sha1, sha256, etc.)
chunk_size: Size of chunks to read
Returns:
str: Hexadecimal digest of the hash
"""
hash_obj = hashlib.new(algorithm)
with open(file_path, "rb") as f:
for chunk in iter(lambda: f.read(chunk_size), b""):
hash_obj.update(chunk)
return hash_obj.hexdigest()
[docs]
def hash_string(string: str, algorithm: str = "sha256") -> str:
hash_obj = hashlib.new(algorithm)
hash_obj.update(string.encode())
return hash_obj.hexdigest()
[docs]
def hash_file_object(
file_obj: BinaryIO, algorithm: str = "sha256", chunk_size: int = 8192
) -> str:
"""
Calculate hash of a file-like object.
Args:
file_obj: File-like object (must be in binary mode)
algorithm: Hash algorithm (md5, sha1, sha256, etc.)
chunk_size: Size of chunks to read
Returns:
str: Hexadecimal digest of the hash
"""
hash_obj = hashlib.new(algorithm)
# Store current position
try:
original_position = file_obj.tell()
except (OSError, IOError, AttributeError):
original_position = None
# Seek to the beginning if possible
try:
file_obj.seek(0)
except (OSError, IOError, AttributeError):
pass
# Calculate hash
for chunk in iter(lambda: file_obj.read(chunk_size), b""):
hash_obj.update(chunk)
# Restore original position if possible
if original_position is not None:
try:
file_obj.seek(original_position)
except (OSError, IOError, AttributeError):
pass
return hash_obj.hexdigest()