Skip to content

Commit

Permalink
Handle IO error on document save (#961)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
vkbo authored Jan 19, 2022
1 parent 8b603d1 commit ec07ceb
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 2 deletions.
6 changes: 5 additions & 1 deletion novelwriter/core/document.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,11 @@ def writeDocument(self, docText, forceWrite=False):

# 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
Expand Down
2 changes: 1 addition & 1 deletion novelwriter/core/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -715,7 +715,7 @@ def saveProject(self, autoSave=False):
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)
Expand Down
12 changes: 12 additions & 0 deletions tests/test_core/test_core_document.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit ec07ceb

Please sign in to comment.