"""Atomare Datei-Writes: erst .tmp im selben Verzeichnis, dann os.replace.

Ein Crash hinterlässt höchstens eine .tmp-Datei — nie eine halb geschriebene
Zieldatei. Die .tmp wird beim nächsten erfolgreichen Write überschrieben.
"""

import json
import os
from pathlib import Path


def atomic_write_text(path: Path, text: str) -> None:
    tmp = path.with_name(path.name + ".tmp")
    with open(tmp, "w", encoding="utf-8") as f:
        f.write(text)
        f.flush()
        os.fsync(f.fileno())
    os.replace(tmp, path)


def atomic_write_json(path: Path, obj, **dumps_kwargs) -> None:
    atomic_write_text(path, json.dumps(obj, ensure_ascii=False, **dumps_kwargs))
