From ec07cebb51650dcd94ca363fdf4a2863624095b0 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Wed, 19 Jan 2022 19:13:08 +0100 Subject: [PATCH] Handle IO error on document save (#961) * Add try/except to document replace call * Try the os.replace command 5 times * Just use else condition on for loop instead * Make the exceptions explicitly OSError * Revert the os.replace loop, as this is not the issue --- novelwriter/core/document.py | 6 +++++- novelwriter/core/project.py | 2 +- tests/test_core/test_core_document.py | 12 ++++++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/novelwriter/core/document.py b/novelwriter/core/document.py index 33894c05..71916af8 100644 --- a/novelwriter/core/document.py +++ b/novelwriter/core/document.py @@ -162,7 +162,11 @@ class NWDoc(): # If we're here, the file was successfully saved, so we can # replace the temp file with the actual file - os.replace(docTemp, docPath) + try: + os.replace(docTemp, docPath) + except OSError as exc: + self._docError = formatException(exc) + return False self._prevHash = sha256sum(docPath) self._currHash = self._prevHash diff --git a/novelwriter/core/project.py b/novelwriter/core/project.py index 7c1e7e26..8e5a8f6e 100644 --- a/novelwriter/core/project.py +++ b/novelwriter/core/project.py @@ -715,7 +715,7 @@ class NWProject(): if os.path.isfile(saveFile): os.replace(saveFile, backFile) os.replace(tempFile, saveFile) - except Exception as exc: + except OSError as exc: self.theParent.makeAlert(self.tr( "Failed to save project." ), nwAlert.ERROR, exception=exc) diff --git a/tests/test_core/test_core_document.py b/tests/test_core/test_core_document.py index 472b74e3..eb7794b5 100644 --- a/tests/test_core/test_core_document.py +++ b/tests/test_core/test_core_document.py @@ -112,6 +112,18 @@ def testCoreDocument_LoadSave(monkeypatch, mockGUI, nwMinimal): assert theDoc.writeDocument(theText) is False assert theDoc.getError() == "OSError: Mock OSError" + theDoc._docError = "" + assert theDoc.getError() == "" + + # Cause os.replace() to fail while saving + with monkeypatch.context() as mp: + mp.setattr("os.replace", causeOSError) + assert theDoc.writeDocument(theText) is False + assert theDoc.getError() == "OSError: Mock OSError" + + theDoc._docError = "" + assert theDoc.getError() == "" + # Saving with no handle theDoc._docHandle = None assert theDoc.writeDocument(theText) is False