atomic_write context to save configs first to temp file, then move
Should prevent corruption of files
(cherry picked from commit c6d0290)
This commit is contained in:
parent
10dc7e4976
commit
d0fadb1b6f
3 changed files with 27 additions and 9 deletions
|
|
@ -329,12 +329,14 @@ class PrinterProfileManager(object):
|
|||
if os.path.exists(path) and not allow_overwrite:
|
||||
raise SaveError("Profile %s already exists and not allowed to overwrite" % profile["id"])
|
||||
|
||||
from octoprint.util import atomic_write
|
||||
import yaml
|
||||
with open(path, "wb") as f:
|
||||
try:
|
||||
try:
|
||||
with atomic_write(path, "wb") as f:
|
||||
yaml.safe_dump(profile, f, default_flow_style=False, indent=" ", allow_unicode=True)
|
||||
except Exception as e:
|
||||
raise SaveError("Cannot save profile %s: %s" % (profile["id"], str(e)))
|
||||
except Exception as e:
|
||||
self._logger.exception("Error while trying to save profile %s" % profile["id"])
|
||||
raise SaveError("Cannot save profile %s: %s" % (profile["id"], str(e)))
|
||||
|
||||
def _remove_from_path(self, path):
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -784,11 +784,17 @@ class Settings(object):
|
|||
if not self._dirty and not force:
|
||||
return False
|
||||
|
||||
with open(self._configfile, "wb") as configFile:
|
||||
yaml.safe_dump(self._config, configFile, default_flow_style=False, indent=" ", allow_unicode=True)
|
||||
self._dirty = False
|
||||
self.load()
|
||||
return True
|
||||
from octoprint.util import atomic_write
|
||||
try:
|
||||
with atomic_write(self._configfile, "wb", prefix="octoprint-config-", suffix=".yaml") as configFile:
|
||||
yaml.safe_dump(self._config, configFile, default_flow_style=False, indent=" ", allow_unicode=True)
|
||||
self._dirty = False
|
||||
except:
|
||||
self._logger.exception("Error while saving config.yaml!")
|
||||
raise
|
||||
else:
|
||||
self.load()
|
||||
return True
|
||||
|
||||
@property
|
||||
def last_modified(self):
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import shutil
|
|||
import threading
|
||||
from functools import wraps
|
||||
import warnings
|
||||
import contextlib
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
|
@ -513,6 +514,15 @@ def address_for_client(host, port):
|
|||
except:
|
||||
continue
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def atomic_write(filename, mode="w+b", prefix="tmp", suffix=""):
|
||||
temp_config = tempfile.NamedTemporaryFile(mode=mode, prefix=prefix, suffix=suffix, delete=False)
|
||||
yield temp_config
|
||||
temp_config.close()
|
||||
shutil.move(temp_config.name, filename)
|
||||
|
||||
|
||||
class RepeatedTimer(threading.Thread):
|
||||
"""
|
||||
This class represents an action that should be run repeatedly in an interval. It is similar to python's
|
||||
|
|
|
|||
Loading…
Reference in a new issue