- 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>
38 lines
1.5 KiB
Python
38 lines
1.5 KiB
Python
"""Источник: synthetic-group/gen/xlsx.py (#35). Детерминированное сохранение xlsx: фиксированные метки книги и записей zip."""
|
|
|
|
import datetime
|
|
import io
|
|
import re
|
|
import zipfile
|
|
from pathlib import Path
|
|
|
|
import openpyxl
|
|
|
|
FIXED_TIME = datetime.datetime(2026, 1, 1, 0, 0, 0)
|
|
ZIP_DATE_TIME = (2026, 1, 1, 0, 0, 0)
|
|
CREATOR = "arm-ka synthetic"
|
|
_FIXED_W3CDTF = FIXED_TIME.strftime("%Y-%m-%dT%H:%M:%SZ").encode()
|
|
_CORE_PART = "docProps/core.xml"
|
|
_MODIFIED_RE = re.compile(rb"(<dcterms:modified[^>]*>)[^<]*(</dcterms:modified>)")
|
|
|
|
|
|
def save_deterministic(wb: openpyxl.Workbook, path: Path) -> None:
|
|
wb.properties.creator = CREATOR
|
|
wb.properties.lastModifiedBy = CREATOR
|
|
wb.properties.created = FIXED_TIME
|
|
wb.properties.modified = FIXED_TIME
|
|
raw = io.BytesIO()
|
|
wb.save(raw)
|
|
out = io.BytesIO()
|
|
with zipfile.ZipFile(raw) as source, zipfile.ZipFile(out, "w", zipfile.ZIP_DEFLATED) as target:
|
|
for info in source.infolist():
|
|
clone = zipfile.ZipInfo(info.filename, date_time=ZIP_DATE_TIME)
|
|
clone.compress_type = zipfile.ZIP_DEFLATED
|
|
clone.external_attr = info.external_attr
|
|
content = source.read(info.filename)
|
|
if info.filename == _CORE_PART:
|
|
content = _MODIFIED_RE.sub(rb"\g<1>" + _FIXED_W3CDTF + rb"\g<2>", content)
|
|
target.writestr(clone, content)
|
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
path.write_bytes(out.getvalue())
|