Source code for simvx.core.io
"""Filesystem I/O helpers shared across the engine.
Centralises crash-safe write patterns so the IDE, scene save, asset writer,
and other consumers share one implementation. The pickle-rotation flavour
lives in ``simvx.core.save_manager.pickle_atomic`` for the (game save +
editor autosave) payloads that need .bak/.bak2 chains.
"""
from __future__ import annotations
import os
from pathlib import Path
[docs]
def atomic_write_text(path: Path | str, text: str, *, encoding: str = "utf-8") -> Path:
"""Write ``text`` to ``path`` atomically.
Writes to ``<path>.tmp``, fsyncs, then ``os.replace()`` onto the target so
a crash mid-write never leaves a truncated file on disk -- either the old
file or the new one is fully present at every instant.
Creates parent directories as needed. Raises ``OSError`` on write failure
(the temp file is best-effort cleaned).
"""
path = Path(path)
path.parent.mkdir(parents=True, exist_ok=True)
tmp_path = path.with_name(path.name + ".tmp")
payload = text.encode(encoding)
try:
with open(tmp_path, "wb") as fh:
fh.write(payload)
fh.flush()
os.fsync(fh.fileno())
except OSError:
try:
tmp_path.unlink()
except OSError:
pass
raise
os.replace(tmp_path, path)
return path