Save config files atomically

Fixes #506.

In PR #377 (save GlobalPrefs atomically), I created a new codepath by
passing a file into yaml.dump. Unfortunately I forgot to mark it as
UTF-8 (regressing #311). This breaks saving settings after opening a
config in a Unicode folder.

To prevent this from recurring, I restructured the code to always pass a
Path into yaml.dump(), and write the file atomically.
pull/507/head
nyanpasu64 2025-05-13 21:02:12 -07:00
rodzic 6a504c51db
commit 4fa08c4f25
3 zmienionych plików z 13 dodań i 8 usunięć

Wyświetl plik

@ -14,6 +14,8 @@
### Changelog
- When opening missing file via CLI, show dialog rather than crashing (#499)
- Fix saving global settings after opening config in Unicode folder (#507)
- Save config files atomically (#507)
## 0.10.1

Wyświetl plik

@ -19,10 +19,10 @@ from typing import (
Any,
TextIO,
Union,
IO,
)
import attr
from atomicwrites import atomic_write
from ruamel.yaml import (
yaml_object,
YAML,
@ -61,9 +61,14 @@ class MyYAML(YAML):
# https://bitbucket.org/ruamel/yaml/issues/316/unicode-encoding-decoding-errors-on
# Both are bad, so use UTF-8.
if isinstance(stream, Path):
with stream.open("w", encoding="utf-8") as f:
path = stream
with atomic_write(path, overwrite=True, encoding="utf-8") as f:
self.dump_without_corrupting(data, f, **kwargs)
elif isinstance(stream, TextIO):
# Nobody actually calls dump(..., open()). This branch is never taken.
self.dump_without_corrupting(data, stream, **kwargs)
elif stream is None:
# Possibly only called in unit tests, not in production.
stream = StringIO()
@ -71,8 +76,9 @@ class MyYAML(YAML):
return stream.getvalue()
else:
# with atomic_write(...) as f: dump(..., f)
self.dump_without_corrupting(data, stream, **kwargs)
raise TypeError(
f"stream must be {{Path, TextIO=open(), None}}, but is {type(stream)}"
)
def dump_without_corrupting(self, *args, **kwargs):
YAML.dump(self, *args, **kwargs)

Wyświetl plik

@ -1,8 +1,6 @@
from typing import *
import attr
from atomicwrites import atomic_write
from corrscope.config import DumpableAttrs, yaml
from corrscope.settings import paths
@ -75,5 +73,4 @@ def load_prefs() -> GlobalPrefs:
def dump_prefs(pref: GlobalPrefs) -> None:
with atomic_write(_PREF_PATH, overwrite=True, encoding="utf-8") as f:
yaml.dump(pref, f)
yaml.dump(pref, _PREF_PATH)