Coverage for / home / jenkins / .local / lib / python3.10 / site-packages / hyper_parallel / codegen / hash.py: 47%
19 statements
« prev ^ index » next coverage.py v7.13.1, created at 2026-10-25 05:45 +0800
« prev ^ index » next coverage.py v7.13.1, created at 2026-10-25 05:45 +0800
1# Copyright 2026 Huawei Technologies Co., Ltd
2# Licensed under the Apache License, Version 2.0
3# ============================================================================
4"""Signature and file-hash helpers for codegen artifacts.
6``signature_from_spec`` is the single source of truth for artifact reuse:
7same canonical spec => same signature => artifact hit. Any change to the
8source modeling file, parallel topology, override set, or checkpoint
9transform flags must change the signature.
10"""
11from __future__ import annotations
13import hashlib
14import json
17def sha256_file(path: str) -> str:
18 """Compute the sha256 of a file's bytes."""
19 digest = hashlib.sha256()
20 with open(path, "rb") as handle:
21 for chunk in iter(lambda: handle.read(1 << 20), b""):
22 digest.update(chunk)
23 return digest.hexdigest()
26def sha256_text(text: str) -> str:
27 """Compute the sha256 of a UTF-8 text payload."""
28 return hashlib.sha256(text.encode("utf-8")).hexdigest()
31def canonical_json(data: object) -> str:
32 """Stable JSON serialization (sorted keys, no whitespace).
34 Used for signature inputs — key order must not affect the digest.
35 """
36 return json.dumps(data, sort_keys=True, separators=(",", ":"), ensure_ascii=True)
39def signature_from_spec(spec: object, *, prefix: int = 12) -> str:
40 """Compute the artifact signature from a canonical spec, first ``prefix`` hex chars.
42 ``spec`` may be any JSON-serializable object (typically a
43 :class:`CodegenSpec` ``to_dict()`` result or its canonical projection).
44 """
45 return sha256_text(canonical_json(spec))[:prefix]
48def file_line_count(path: str) -> int:
49 """Count lines in a text file."""
50 with open(path, "r", encoding="utf-8") as handle:
51 return sum(1 for _ in handle)
54__all__ = [
55 "canonical_json",
56 "file_line_count",
57 "sha256_file",
58 "sha256_text",
59 "signature_from_spec",
60]