Paya / code /paya /atomic.py
yeabwang's picture
Paya model bundle and revised model card
534cc76
Raw History Blame Contribute Delete
939 Bytes
"""Publish complete files without replacing a usable file after a failed write."""
from contextlib import contextmanager
import os
from pathlib import Path
import tempfile
@contextmanager
def atomic_output(path, mode="wb"):
path = Path(path)
path.parent.mkdir(parents=True, exist_ok=True)
handle = tempfile.NamedTemporaryFile(mode=mode, dir=path.parent,
prefix=path.name + ".", suffix=".partial", delete=False,
**({"encoding": "utf-8"} if "b" not in mode else {}))
temporary = Path(handle.name)
try:
with handle:
yield handle
handle.flush()
os.fsync(handle.fileno())
os.replace(temporary, path)
if os.name != "nt":
descriptor = os.open(path.parent, os.O_RDONLY)
try:
os.fsync(descriptor)
finally:
os.close(descriptor)
finally:
temporary.unlink(missing_ok=True)