Source code for elasticai.creator.hw_function_id
import logging
from collections.abc import Callable, Iterable, Iterator
from hashlib import blake2b, file_digest
from pathlib import Path
[docs]
class HwFunctionIdUpdater:
def __init__(
self,
build_dir: Path,
target_file: str | Path,
replace_id_fn: Callable[[Iterable[str], bytes], Iterator[str]],
):
self._target_file = Path(target_file).relative_to(build_dir)
self._build_dir = build_dir
self._id = bytes()
self._replace_id_fn = replace_id_fn
def _files_from_build_dir(self) -> Iterator[Path]:
for f in self._build_dir.glob("**/*"):
if f.is_file():
yield f
def _is_not_target_file(self, file: Path) -> bool:
return not file.samefile(self._target_file)
def _collect_files_to_hash(self) -> Iterator[Path]:
return filter(self._is_not_target_file, self._files_from_build_dir())
[docs]
def compute_id(self) -> None:
logger = logging.getLogger(__name__)
hash = _HwFunctionIdHash()
for vhd_file in self._collect_files_to_hash():
logger.debug(f"hashing {vhd_file.as_uri}")
hash.update(vhd_file)
digest = hash.digest()
logger.debug(f"raw_digest is {digest.hex()}")
self._id = digest
[docs]
def write_id(self) -> None:
with open(self._target_file, "r") as f:
code: Iterable[str] = f.readlines()
code = self._replace_id_fn(code, self.id)
with open(self._target_file, "w") as f:
for line in code:
f.write(line)
f.write("\n")
@property
def id(self) -> bytes:
return self._id
class _HwFunctionIdHash:
SIZE: int = 16
def __init__(self):
self._digests = []
def _hash(self):
return blake2b(digest_size=self.SIZE)
def update(self, lines: Iterable[str] | Path) -> None:
h = self._hash()
if isinstance(lines, Path):
with open(lines, "rb") as f:
self._digests.append(file_digest(f, self._hash).digest())
else:
for line in lines:
h.update(line.encode())
self._digests.append(h.digest())
def digest(self) -> bytes:
h = self._hash()
for d in sorted(self._digests):
h.update(d)
return h.digest()