Andrey Epifancev 801d9948ca synthgen: каркас, настройки, копии модулей #35 (#38)
- synthgen/config.py: Config, load_config (YAML + --set), dump_config, проверки диапазонов §3
- synthgen/rng.py: rng_for (SHA-256 → Random), stable_hash
- synthgen/__main__.py: разбор --config/--set/--out/--force, ошибка конфигурации → код 2
- synthgen/examples/default.yaml: все ключи §3 со значениями по умолчанию
- копии из synthetic-group/gen (#35): inn, xlsx, ledger, chart (+80.09, 91.09 из seed arm-core)
- тесты: config, inn, ledger; conftest с маркерами parser/slow
- .gitignore: out/
- спека: решения 15–16

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
2026-11-12 23:35:17 +04:00

20 lines
1.1 KiB
Python

"""Детерминированная случайность: одно зерно на каждую подсистему.
Любая случайность в генераторе — только через `rng_for(seed, *keys)`; модульный `random` запрещён.
Ключи должны иметь стабильный `repr` (строки, числа, даты, кортежи из них).
"""
import hashlib
import random
def rng_for(seed: int, *keys: object) -> random.Random:
"""Генератор, зерно = первые 8 байт SHA-256 от repr((seed, *keys)) (порядок байт — big-endian)."""
digest = hashlib.sha256(repr((seed, *keys)).encode("utf-8")).digest()
return random.Random(int.from_bytes(digest[:8], "big"))
def stable_hash(text: str, modulo: int) -> int:
"""Стабильный хеш строки (SHA-256 → целое → остаток); в отличие от hash() не зависит от PYTHONHASHSEED."""
return int.from_bytes(hashlib.sha256(text.encode("utf-8")).digest(), "big") % modulo