kopia lustrzana https://github.com/corrscope/corrscope
Merge pull request #377 from corrscope/fix-config-crash
commit
e3e414e28c
|
@ -3,6 +3,8 @@
|
||||||
### Changelog
|
### Changelog
|
||||||
|
|
||||||
- Update NumPy so `poetry install` on Python 3.8+ won't build NumPy from source (#371)
|
- Update NumPy so `poetry install` on Python 3.8+ won't build NumPy from source (#371)
|
||||||
|
- Fix longstanding crash when prefs.yaml is corrupted, reset settings instead (#377)
|
||||||
|
- Atomically save prefs.yaml to prevent file corruption (#377)
|
||||||
|
|
||||||
## 0.7.0
|
## 0.7.0
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ from typing import (
|
||||||
Any,
|
Any,
|
||||||
TextIO,
|
TextIO,
|
||||||
Union,
|
Union,
|
||||||
|
IO,
|
||||||
)
|
)
|
||||||
|
|
||||||
import attr
|
import attr
|
||||||
|
@ -64,10 +65,6 @@ class MyYAML(YAML):
|
||||||
with stream.open("w", encoding="utf-8") as f:
|
with stream.open("w", encoding="utf-8") as f:
|
||||||
self.dump_without_corrupting(data, f, **kwargs)
|
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:
|
elif stream is None:
|
||||||
# Possibly only called in unit tests, not in production.
|
# Possibly only called in unit tests, not in production.
|
||||||
stream = StringIO()
|
stream = StringIO()
|
||||||
|
@ -75,9 +72,8 @@ class MyYAML(YAML):
|
||||||
return stream.getvalue()
|
return stream.getvalue()
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise TypeError(
|
# with atomic_write(...) as f: dump(..., f)
|
||||||
f"stream must be {{Path, TextIO=open(), None}}, but is {type(stream)}"
|
self.dump_without_corrupting(data, stream, **kwargs)
|
||||||
)
|
|
||||||
|
|
||||||
def dump_without_corrupting(self, *args, **kwargs):
|
def dump_without_corrupting(self, *args, **kwargs):
|
||||||
YAML.dump(self, *args, **kwargs)
|
YAML.dump(self, *args, **kwargs)
|
||||||
|
|
|
@ -175,7 +175,14 @@ class MainWindow(qw.QMainWindow, Ui_MainWindow):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
# Load settings.
|
# Load settings.
|
||||||
self.pref = gp.load_prefs()
|
prefs_error = None
|
||||||
|
try:
|
||||||
|
self.pref = gp.load_prefs()
|
||||||
|
if not isinstance(self.pref, gp.GlobalPrefs):
|
||||||
|
raise TypeError(f"prefs.yaml contains wrong type {type(self.pref)}")
|
||||||
|
except Exception as e:
|
||||||
|
prefs_error = e
|
||||||
|
self.pref = gp.GlobalPrefs()
|
||||||
|
|
||||||
# Load UI.
|
# Load UI.
|
||||||
self.setupUi(self) # sets windowTitle
|
self.setupUi(self) # sets windowTitle
|
||||||
|
@ -237,6 +244,12 @@ class MainWindow(qw.QMainWindow, Ui_MainWindow):
|
||||||
|
|
||||||
self.show()
|
self.show()
|
||||||
|
|
||||||
|
if prefs_error is not None:
|
||||||
|
TracebackDialog(self).showMessage(
|
||||||
|
"Warning: failed to load global preferences, resetting to default.\n"
|
||||||
|
+ format_stack_trace(prefs_error)
|
||||||
|
)
|
||||||
|
|
||||||
_cfg_path: Optional[Path]
|
_cfg_path: Optional[Path]
|
||||||
|
|
||||||
# Whether document is dirty, changed, has unsaved changes
|
# Whether document is dirty, changed, has unsaved changes
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
from typing import *
|
from typing import *
|
||||||
|
|
||||||
|
from atomicwrites import atomic_write
|
||||||
|
|
||||||
from corrscope.config import DumpableAttrs, yaml
|
from corrscope.config import DumpableAttrs, yaml
|
||||||
from corrscope.settings import paths
|
from corrscope.settings import paths
|
||||||
|
|
||||||
|
@ -50,4 +52,5 @@ def load_prefs() -> GlobalPrefs:
|
||||||
|
|
||||||
|
|
||||||
def dump_prefs(pref: GlobalPrefs) -> None:
|
def dump_prefs(pref: GlobalPrefs) -> None:
|
||||||
yaml.dump(pref, _PREF_PATH)
|
with atomic_write(_PREF_PATH, overwrite=True) as f:
|
||||||
|
yaml.dump(pref, f)
|
||||||
|
|
|
@ -18,7 +18,7 @@ python-versions = "*"
|
||||||
name = "atomicwrites"
|
name = "atomicwrites"
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
description = "Atomic file writes."
|
description = "Atomic file writes."
|
||||||
category = "dev"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||||
|
|
||||||
|
@ -609,7 +609,7 @@ testing = ["pytest (>=4.6)", "pytest-checkdocs (>=1.2.3)", "pytest-flake8", "pyt
|
||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "1.1"
|
lock-version = "1.1"
|
||||||
python-versions = "^3.6.2"
|
python-versions = "^3.6.2"
|
||||||
content-hash = "7e4bd31660cb4764c68a7f51487837972530c1426c7902c04ca760d5ef278fa5"
|
content-hash = "bb03d24e8ec7fcbf38ca0726736a7cdcd3e3f38a2ad281f522e3aedce1540bfb"
|
||||||
|
|
||||||
[metadata.files]
|
[metadata.files]
|
||||||
altgraph = [
|
altgraph = [
|
||||||
|
|
|
@ -27,6 +27,7 @@ matplotlib = "^3.1"
|
||||||
attrs = "^21.2.0"
|
attrs = "^21.2.0"
|
||||||
PyQt5 = "^5.15.4"
|
PyQt5 = "^5.15.4"
|
||||||
appdirs = "^1.4.4"
|
appdirs = "^1.4.4"
|
||||||
|
atomicwrites = "^1.4.0"
|
||||||
|
|
||||||
[tool.poetry.dev-dependencies]
|
[tool.poetry.dev-dependencies]
|
||||||
pytest = "^6.2.4"
|
pytest = "^6.2.4"
|
||||||
|
|
Ładowanie…
Reference in New Issue