here.platform.utils.file

Source code for here.platform.utils.file

Copyright (C) 2020-2022 HERE Global B.V. and its affiliate(s).

All rights reserved.

This software and other materials contain proprietary information

controlled by HERE and are protected by applicable copyright legislation.

Any use and utilization of this software and other materials and

disclosure to any third parties is conditional upon having a separate

agreement with HERE for the access, use, utilization or disclosure of this

software. In the absence of such agreement, the use of the software is not

allowed.

"""
This module contains helper functions for various file operations.
"""

import hashlib
import zlib
from pathlib import Path
from typing import Optional, Union

[docs]
def checksum(
path_or_data: Union[str, Path, bytes], hash_algo: str, chunk_num_blocks: int = 128
) -> str:
"""
Calculate checksum for data in a file based on input hashing algorithm.

:param path_or_data: A string representing path of the file.
:param hash_algo: A string representing name of hashing algorithm.
:param chunk_num_blocks: An int representing block size.
:return: A checksum string.
:raises ValueError: If file does not exist or hash_algo is not valid.
"""
hash_algo = (hash_algo.replace("-", "")).lower()
if hash_algo not in hashlib.algorithms_guaranteed:
raise ValueError(f"Algorithm {hash_algo} is not supported by hashlib.")
hash_factory = getattr(hashlib, hash_algo)
hash_obj = hash_factory()
if isinstance(path_or_data, bytes):
hash_obj.update(path_or_data)
else:
if not Path(path_or_data).is_file():
raise ValueError(f"File: {path_or_data} does not exist.")
with open(path_or_data, "rb") as f:
for chunk in iter(lambda: f.read(chunk_num_blocks * hash_obj.block_size), b""):
hash_obj.update(chunk)
return str(hash_obj.hexdigest())

[docs]
def get_crc(path_or_data: Union[str, Path, bytes]):
"""
Calculate crc for data.
"""
crc: Optional[str] = None
if isinstance(path_or_data, bytes):
crc = str(zlib.crc32(path_or_data))
crc = "%X" % (int(crc) & 0xFFFFFFFF)
else:
buffersize = 262144 # 256 KB
with open(path_or_data, "rb") as afile:
buffr = afile.read(buffersize)
crcvalue = 0
while len(buffr) > 0:
crcvalue = zlib.crc32(buffr, crcvalue)
buffr = afile.read(buffersize)
crc = "%X" % (crcvalue & 0xFFFFFFFF)
return crc

[docs]
def get_readable_bytes(size: int) -> str:
"""
Get a human-readable representation of the given number of bytes.

:param size: the number of bytes
:return: the size scaled to KB, MB, GB or TB with units
"""
power_labels = {40: "TB", 30: "GB", 20: "MB", 10: "KB"}
for power, label in power_labels.items():
if size >= 2power:
approx_size = size // 2
power
return f"{approx_size} {label}"
return f"{size} bytes"