NODEDC_MISSION_CORE/src/k1link/artifacts.py

40 lines
1.2 KiB
Python

from __future__ import annotations
import json
import os
import tempfile
from datetime import UTC, datetime
from pathlib import Path
from typing import Any
def utc_now_iso() -> str:
"""Return a stable UTC timestamp for manifests and capture artifacts."""
return datetime.now(UTC).isoformat(timespec="milliseconds").replace("+00:00", "Z")
def write_json_atomic(path: Path, payload: Any) -> None:
"""Write JSON without exposing a partially written artifact."""
path = path.expanduser()
path.parent.mkdir(parents=True, exist_ok=True)
serialized = json.dumps(payload, ensure_ascii=False, indent=2) + "\n"
temp_name: str | None = None
try:
with tempfile.NamedTemporaryFile(
mode="w",
encoding="utf-8",
dir=path.parent,
prefix=f".{path.name}.",
suffix=".tmp",
delete=False,
) as stream:
temp_name = stream.name
stream.write(serialized)
stream.flush()
os.fsync(stream.fileno())
Path(temp_name).replace(path)
finally:
if temp_name is not None:
Path(temp_name).unlink(missing_ok=True)