Coverage for app/venv/lib/python3.14/site-packages/weblate/utils/hash.py: 79%
22 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 07:15 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 07:15 +0000
1# Copyright © Michal Čihař <michal@weblate.org>
2#
3# SPDX-License-Identifier: GPL-3.0-or-later
5from __future__ import annotations
7from typing import TYPE_CHECKING, Any
9from siphashc import siphash
11if TYPE_CHECKING: 11 ↛ 12line 11 didn't jump to line 12 because the condition on line 11 was never true
12 from collections.abc import Mapping
15def raw_hash(*parts: str) -> int:
16 """Calculate checksum identifying translation."""
17 if not parts: 17 ↛ 18line 17 didn't jump to line 18 because the condition on line 17 was never true
18 data = ""
19 elif len(parts) == 1:
20 data = parts[0]
21 else:
22 data = "".join(part for part in parts)
23 return siphash("Weblate Sip Hash", data)
26def calculate_dict_hash(data: Mapping[str, Any]) -> int:
27 """
28 Calculate checksum of a dict.
30 * Ordering independent.
31 * Coerces all values to string.
33 Returns unsigned int.
34 """
35 return raw_hash(*(f"{part[0]}:{part[1]}" for part in sorted(data.items())))
38def calculate_hash(*parts: str) -> int:
39 """Calculate checksum identifying translation."""
40 # Need to convert it from unsigned 64-bit int to signed 64-bit int
41 return raw_hash(*parts) - 2**63
44def calculate_checksum(*parts: str) -> str:
45 """Calculate siphashc checksum for given strings."""
46 return format(raw_hash(*parts), "016x")
49def checksum_to_hash(checksum: str) -> int:
50 """Convert hex to id_hash (signed 64-bit int)."""
51 return int(checksum, 16) - 2**63
54def hash_to_checksum(id_hash: int) -> str:
55 """Convert id_hash (signed 64-bit int) to unsigned hex."""
56 return format(id_hash + 2**63, "016x")