Error logging and mutables as function defaults (#930)

* Remove mutable iterables as function defaults
* Improve error reporting and standardise how it's done
This commit is contained in:
Veronica Berglyd Olsen
2021-11-10 00:32:01 +01:00
committed by GitHub
parent 67d2e266fd
commit 00eea24e3f
15 changed files with 88 additions and 65 deletions
+7 -7
View File
@@ -36,7 +36,7 @@ from PyQt5.QtCore import (
QTranslator QTranslator
) )
from novelwriter.error import logException from novelwriter.error import logException, formatException
from novelwriter.common import splitVersionNumber, formatTimeStamp, NWConfigParser from novelwriter.common import splitVersionNumber, formatTimeStamp, NWConfigParser
from novelwriter.constants import nwFiles, nwUnicode from novelwriter.constants import nwFiles, nwUnicode
@@ -312,7 +312,7 @@ class Config:
logException() logException()
self.hasError = True self.hasError = True
self.errData.append("Could not create folder: %s" % self.confPath) self.errData.append("Could not create folder: %s" % self.confPath)
self.errData.append(str(exc)) self.errData.append(formatException(exc))
self.confPath = None self.confPath = None
# Check if config file exists # Check if config file exists
@@ -335,7 +335,7 @@ class Config:
logException() logException()
self.hasError = True self.hasError = True
self.errData.append("Could not create folder: %s" % self.dataPath) self.errData.append("Could not create folder: %s" % self.dataPath)
self.errData.append(str(exc)) self.errData.append(formatException(exc))
self.dataPath = None self.dataPath = None
# Host and Kernel # Host and Kernel
@@ -430,7 +430,7 @@ class Config:
logException() logException()
self.hasError = True self.hasError = True
self.errData.append("Could not load config file") self.errData.append("Could not load config file")
self.errData.append(str(exc)) self.errData.append(formatException(exc))
return False return False
# Main # Main
@@ -660,7 +660,7 @@ class Config:
logException() logException()
self.hasError = True self.hasError = True
self.errData.append("Could not save config file") self.errData.append("Could not save config file")
self.errData.append(str(exc)) self.errData.append(formatException(exc))
return False return False
return True return True
@@ -691,7 +691,7 @@ class Config:
except Exception as exc: except Exception as exc:
self.hasError = True self.hasError = True
self.errData.append("Could not load recent project cache") self.errData.append("Could not load recent project cache")
self.errData.append(str(exc)) self.errData.append(formatException(exc))
return False return False
return True return True
@@ -711,7 +711,7 @@ class Config:
except Exception as exc: except Exception as exc:
self.hasError = True self.hasError = True
self.errData.append("Could not save recent project cache") self.errData.append("Could not save recent project cache")
self.errData.append(str(exc)) self.errData.append(formatException(exc))
return False return False
if os.path.isfile(cacheFile): if os.path.isfile(cacheFile):
+5 -4
View File
@@ -27,6 +27,7 @@ import os
import logging import logging
from novelwriter.enum import nwItemLayout, nwItemClass from novelwriter.enum import nwItemLayout, nwItemClass
from novelwriter.error import formatException
from novelwriter.common import isHandle, sha256sum from novelwriter.common import isHandle, sha256sum
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -101,7 +102,7 @@ class NWDoc():
theText += inFile.read() theText += inFile.read()
except Exception as exc: except Exception as exc:
self._docError = str(exc) self._docError = formatException(exc)
return None return None
else: else:
@@ -150,7 +151,7 @@ class NWDoc():
outFile.write(docMeta) outFile.write(docMeta)
outFile.write(docText) outFile.write(docText)
except Exception as exc: except Exception as exc:
self._docError = str(exc) self._docError = formatException(exc)
return False return False
# If we're here, the file was successfully saved, so we can # If we're here, the file was successfully saved, so we can
@@ -185,7 +186,7 @@ class NWDoc():
os.unlink(chkFile) os.unlink(chkFile)
logger.debug("Deleted: %s", chkFile) logger.debug("Deleted: %s", chkFile)
except Exception as exc: except Exception as exc:
self._docError = str(exc) self._docError = formatException(exc)
return False return False
return True return True
@@ -225,7 +226,7 @@ class NWDoc():
## ##
def _parseMeta(self, metaLine): def _parseMeta(self, metaLine):
"""Parse a line from the document statting with the characters """Parse a line from the document starting with the characters
%%~ that may contain meta data. %%~ that may contain meta data.
""" """
if metaLine.startswith("%%~name:"): if metaLine.startswith("%%~name:"):
+4 -3
View File
@@ -32,6 +32,7 @@ import novelwriter
from time import time from time import time
from novelwriter.enum import nwItemType, nwItemClass, nwItemLayout from novelwriter.enum import nwItemType, nwItemClass, nwItemLayout
from novelwriter.error import logException
from novelwriter.constants import nwFiles, nwKeyWords, nwUnicode from novelwriter.constants import nwFiles, nwKeyWords, nwUnicode
from novelwriter.core.document import NWDoc from novelwriter.core.document import NWDoc
from novelwriter.common import ( from novelwriter.common import (
@@ -155,7 +156,7 @@ class NWIndex():
except Exception: except Exception:
logger.error("Failed to load index file") logger.error("Failed to load index file")
novelwriter.logException() logException()
self.indexBroken = True self.indexBroken = True
return False return False
@@ -194,7 +195,7 @@ class NWIndex():
except Exception: except Exception:
logger.error("Failed to save index file") logger.error("Failed to save index file")
novelwriter.logException() logException()
return False return False
logger.verbose("Index saved in %.3f ms", (time() - tStart)*1000) logger.verbose("Index saved in %.3f ms", (time() - tStart)*1000)
@@ -217,7 +218,7 @@ class NWIndex():
except Exception: except Exception:
logger.error("Error while checking index") logger.error("Error while checking index")
novelwriter.logException() logException()
self.indexBroken = True self.indexBroken = True
logger.verbose("Index check took %.3f ms", (time() - tStart)*1000) logger.verbose("Index check took %.3f ms", (time() - tStart)*1000)
+4 -4
View File
@@ -27,10 +27,10 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
import os import os
import json import json
import logging import logging
import novelwriter
from novelwriter.constants import nwFiles from novelwriter.error import logException
from novelwriter.common import checkBool, checkFloat, checkInt, checkString from novelwriter.common import checkBool, checkFloat, checkInt, checkString
from novelwriter.constants import nwFiles
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -86,7 +86,7 @@ class OptionState():
theState = json.load(inFile) theState = json.load(inFile)
except Exception: except Exception:
logger.error("Failed to load GUI options file") logger.error("Failed to load GUI options file")
novelwriter.logException() logException()
return False return False
# Filter out unused variables # Filter out unused variables
@@ -113,7 +113,7 @@ class OptionState():
json.dump(self._theState, outFile, indent=2) json.dump(self._theState, outFile, indent=2)
except Exception: except Exception:
logger.error("Failed to save GUI options file") logger.error("Failed to save GUI options file")
novelwriter.logException() logException()
return False return False
return True return True
+17 -13
View File
@@ -37,14 +37,15 @@ from PyQt5.QtCore import QCoreApplication
from novelwriter.core.tree import NWTree from novelwriter.core.tree import NWTree
from novelwriter.core.item import NWItem from novelwriter.core.item import NWItem
from novelwriter.core.document import NWDoc
from novelwriter.core.status import NWStatus from novelwriter.core.status import NWStatus
from novelwriter.core.options import OptionState from novelwriter.core.options import OptionState
from novelwriter.core.document import NWDoc
from novelwriter.enum import nwItemType, nwItemClass, nwItemLayout, nwAlert
from novelwriter.error import logException
from novelwriter.common import ( from novelwriter.common import (
checkString, checkBool, checkInt, isHandle, formatTimeStamp, checkString, checkBool, checkInt, isHandle, formatTimeStamp,
makeFileNameSafe, hexToInt makeFileNameSafe, hexToInt
) )
from novelwriter.enum import nwItemType, nwItemClass, nwItemLayout, nwAlert
from novelwriter.constants import trConst, nwFiles, nwLabels from novelwriter.constants import trConst, nwFiles, nwLabels
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -236,10 +237,13 @@ class NWProject():
return return
def newProject(self, projData={}): def newProject(self, projData=None):
"""Create a new project by populating the project tree with a """Create a new project by populating the project tree with a
few starter items. few starter items.
""" """
if projData is None:
projData = {}
popMinimal = projData.get("popMinimal", True) popMinimal = projData.get("popMinimal", True)
popCustom = projData.get("popCustom", False) popCustom = projData.get("popCustom", False)
popSample = projData.get("popSample", False) popSample = projData.get("popSample", False)
@@ -1252,7 +1256,7 @@ class NWProject():
except Exception: except Exception:
logger.error("Failed to project language file") logger.error("Failed to project language file")
novelwriter.logException() logException()
return False return False
return True return True
@@ -1277,7 +1281,7 @@ class NWProject():
except Exception: except Exception:
logger.error("Failed to read project lockfile") logger.error("Failed to read project lockfile")
novelwriter.logException() logException()
return ["ERROR"] return ["ERROR"]
return theLines return theLines
@@ -1298,7 +1302,7 @@ class NWProject():
except Exception: except Exception:
logger.error("Failed to write project lockfile") logger.error("Failed to write project lockfile")
novelwriter.logException() logException()
return False return False
return True return True
@@ -1315,7 +1319,7 @@ class NWProject():
os.unlink(lockFile) os.unlink(lockFile)
except Exception: except Exception:
logger.error("Failed to remove project lockfile") logger.error("Failed to remove project lockfile")
novelwriter.logException() logException()
return False return False
return True return True
@@ -1488,7 +1492,7 @@ class NWProject():
except Exception: except Exception:
logger.error("Failed to write session stats file") logger.error("Failed to write session stats file")
novelwriter.logException() logException()
return False return False
return True return True
@@ -1526,7 +1530,7 @@ class NWProject():
except Exception: except Exception:
errList.append(self.tr("Could not move: {0}").format(theFile)) errList.append(self.tr("Could not move: {0}").format(theFile))
logger.error("Could not move: %s", theFile) logger.error("Could not move: %s", theFile)
novelwriter.logException() logException()
elif len(dataItem) == 21 and dataItem.endswith("_main.bak"): elif len(dataItem) == 21 and dataItem.endswith("_main.bak"):
try: try:
@@ -1535,7 +1539,7 @@ class NWProject():
except Exception: except Exception:
errList.append(self.tr("Could not delete: {0}").format(theFile)) errList.append(self.tr("Could not delete: {0}").format(theFile))
logger.error("Could not delete: %s", theFile) logger.error("Could not delete: %s", theFile)
novelwriter.logException() logException()
else: else:
theErr = self._moveUnknownItem(theData, dataItem) theErr = self._moveUnknownItem(theData, dataItem)
@@ -1549,7 +1553,7 @@ class NWProject():
except Exception: except Exception:
errList.append(self.tr("Could not delete: {0}").format(theFolder)) errList.append(self.tr("Could not delete: {0}").format(theFolder))
logger.error("Could not delete: %s", theFolder) logger.error("Could not delete: %s", theFolder)
novelwriter.logException() logException()
return errList return errList
@@ -1569,7 +1573,7 @@ class NWProject():
logger.info("Moved to junk: %s", theSrc) logger.info("Moved to junk: %s", theSrc)
except Exception: except Exception:
logger.error("Could not move item %s to junk", theSrc) logger.error("Could not move item %s to junk", theSrc)
novelwriter.logException() logException()
return self.tr("Could not move item {0} to {1}.").format(theSrc, theJunk) return self.tr("Could not move item {0} to {1}.").format(theSrc, theJunk)
return "" return ""
@@ -1604,7 +1608,7 @@ class NWProject():
os.unlink(rmFile) os.unlink(rmFile)
except Exception: except Exception:
logger.error("Could not delete: %s", rmFile) logger.error("Could not delete: %s", rmFile)
novelwriter.logException() logException()
return False return False
return True return True
+5 -3
View File
@@ -27,6 +27,8 @@ import os
import logging import logging
import novelwriter import novelwriter
from novelwriter.error import logException
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -107,7 +109,7 @@ class NWSpellEnchant():
self._projDict.add(newWord) self._projDict.add(newWord)
except Exception: except Exception:
logger.error("Failed to add word to project word list %s", str(self._projectDict)) logger.error("Failed to add word to project word list %s", str(self._projectDict))
novelwriter.logException() logException()
return False return False
return True return True
@@ -135,7 +137,7 @@ class NWSpellEnchant():
spName = self._theDict.provider.name spName = self._theDict.provider.name
except Exception: except Exception:
logger.error("Failed to extract information about the dictionary") logger.error("Failed to extract information about the dictionary")
novelwriter.logException() logException()
spTag = "" spTag = ""
spName = "" spName = ""
@@ -169,7 +171,7 @@ class NWSpellEnchant():
except Exception: except Exception:
logger.error("Failed to load project word list") logger.error("Failed to load project word list")
novelwriter.logException() logException()
return False return False
return True return True
+2 -2
View File
@@ -25,13 +25,13 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
import os import os
import logging import logging
import novelwriter
from time import time from time import time
from lxml import etree from lxml import etree
from hashlib import sha256 from hashlib import sha256
from novelwriter.enum import nwItemType, nwItemClass, nwItemLayout from novelwriter.enum import nwItemType, nwItemClass, nwItemLayout
from novelwriter.error import logException
from novelwriter.common import checkHandle from novelwriter.common import checkHandle
from novelwriter.constants import nwConst, nwFiles from novelwriter.constants import nwConst, nwFiles
from novelwriter.core.item import NWItem from novelwriter.core.item import NWItem
@@ -184,7 +184,7 @@ class NWTree():
except Exception: except Exception:
logger.error("Could not write ToC file") logger.error("Could not write ToC file")
novelwriter.logException() logException()
return False return False
return True return True
+2 -1
View File
@@ -34,6 +34,7 @@ from PyQt5.QtWidgets import (
) )
from novelwriter.enum import nwAlert from novelwriter.enum import nwAlert
from novelwriter.error import logException
from novelwriter.constants import nwFiles from novelwriter.constants import nwFiles
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -161,7 +162,7 @@ class GuiWordList(QDialog):
except Exception: except Exception:
logger.error("Could not save new word list") logger.error("Could not save new word list")
novelwriter.logException() logException()
self.reject() self.reject()
return False return False
+10 -3
View File
@@ -43,7 +43,14 @@ def logException():
"""Log the content of an exception message. """Log the content of an exception message.
""" """
exType, exValue, _ = sys.exc_info() exType, exValue, _ = sys.exc_info()
logger.error("%s: %s", exType.__name__, str(exValue).strip("'")) logger.error("%s: %s", exType.__name__, str(exValue))
def formatException(exc):
"""Format an exception as a string the same way the default
exception handler does.
"""
return f"{type(exc).__name__}: {str(exc)}"
# =============================================================================================== # # =============================================================================================== #
@@ -185,11 +192,11 @@ def exceptionHandler(exType, exValue, exTrace):
except Exception as exc: except Exception as exc:
logger.critical("Could not close the project before exiting") logger.critical("Could not close the project before exiting")
logger.critical(str(exc)) logger.critical(formatException(exc))
qApp.exit(1) qApp.exit(1)
except Exception as exc: except Exception as exc:
logger.critical(str(exc)) logger.critical(formatException(exc))
return return
+2 -1
View File
@@ -41,6 +41,7 @@ from PyQt5.QtWidgets import (
from novelwriter.core import ToHtml from novelwriter.core import ToHtml
from novelwriter.enum import nwAlert, nwItemType, nwDocAction from novelwriter.enum import nwAlert, nwItemType, nwDocAction
from novelwriter.error import logException
from novelwriter.constants import nwUnicode from novelwriter.constants import nwUnicode
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -185,7 +186,7 @@ class GuiDocViewer(QTextBrowser):
aDoc.doPostProcessing() aDoc.doPostProcessing()
except Exception: except Exception:
logger.error("Failed to generate preview for document with handle '%s'", tHandle) logger.error("Failed to generate preview for document with handle '%s'", tHandle)
novelwriter.logException() logException()
self.setText(self.tr("An error occurred while generating the preview.")) self.setText(self.tr("An error occurred while generating the preview."))
return False return False
+5 -4
View File
@@ -37,6 +37,7 @@ from PyQt5.QtGui import (
) )
from novelwriter.enum import nwItemLayout, nwItemType from novelwriter.enum import nwItemLayout, nwItemType
from novelwriter.error import logException
from novelwriter.common import NWConfigParser, readTextFile from novelwriter.common import NWConfigParser, readTextFile
from novelwriter.constants import nwLabels from novelwriter.constants import nwLabels
@@ -250,7 +251,7 @@ class GuiTheme:
confParser.read_file(inFile) confParser.read_file(inFile)
except Exception: except Exception:
logger.error("Could not load theme settings from: %s", self.themeFile) logger.error("Could not load theme settings from: %s", self.themeFile)
novelwriter.logException() logException()
return False return False
# Main # Main
@@ -310,7 +311,7 @@ class GuiTheme:
confParser.read_file(inFile) confParser.read_file(inFile)
except Exception: except Exception:
logger.error("Could not load syntax colours from: %s", self.syntaxFile) logger.error("Could not load syntax colours from: %s", self.syntaxFile)
novelwriter.logException() logException()
return False return False
# Main # Main
@@ -531,7 +532,7 @@ class GuiIcons:
confParser.read_file(inFile) confParser.read_file(inFile)
except Exception: except Exception:
logger.error("Could not load icon theme settings from: %s", themeConf) logger.error("Could not load icon theme settings from: %s", themeConf)
novelwriter.logException() logException()
return False return False
# Main # Main
@@ -729,7 +730,7 @@ def _loadInternalName(confParser, confFile):
confParser.read_file(inFile) confParser.read_file(inFile)
except Exception: except Exception:
logger.error("Could not load file: %s", confFile) logger.error("Could not load file: %s", confFile)
novelwriter.logException() logException()
return "" return ""
return confParser.rdStr("Main", "name", "") return confParser.rdStr("Main", "name", "")
+15 -11
View File
@@ -45,6 +45,7 @@ from PyQt5.QtPrintSupport import QPrinter, QPrintPreviewDialog
from novelwriter.core import ToHtml, ToOdt, ToMarkdown from novelwriter.core import ToHtml, ToOdt, ToMarkdown
from novelwriter.enum import nwAlert, nwItemType, nwItemLayout, nwItemClass from novelwriter.enum import nwAlert, nwItemType, nwItemLayout, nwItemClass
from novelwriter.error import formatException, logException
from novelwriter.common import fuzzyTime, makeFileNameSafe from novelwriter.common import fuzzyTime, makeFileNameSafe
from novelwriter.constants import nwConst, nwFiles from novelwriter.constants import nwConst, nwFiles
from novelwriter.gui.custom import QSwitch from novelwriter.gui.custom import QSwitch
@@ -727,7 +728,7 @@ class GuiBuildNovel(QDialog):
except Exception: except Exception:
logger.error("Failed to build document '%s'", tItem.itemHandle) logger.error("Failed to build document '%s'", tItem.itemHandle)
novelwriter.logException() logException()
if isPreview: if isPreview:
self.docView.setText(( self.docView.setText((
"Failed to generate preview. " "Failed to generate preview. "
@@ -873,7 +874,7 @@ class GuiBuildNovel(QDialog):
makeOdt.saveOpenDocText(savePath) makeOdt.saveOpenDocText(savePath)
wSuccess = True wSuccess = True
except Exception as exc: except Exception as exc:
errMsg = str(exc) errMsg = formatException(exc)
elif theFmt == self.FMT_FODT: elif theFmt == self.FMT_FODT:
makeOdt = ToOdt(self.theProject, isFlat=True) makeOdt = ToOdt(self.theProject, isFlat=True)
@@ -882,7 +883,7 @@ class GuiBuildNovel(QDialog):
makeOdt.saveFlatXML(savePath) makeOdt.saveFlatXML(savePath)
wSuccess = True wSuccess = True
except Exception as exc: except Exception as exc:
errMsg = str(exc) errMsg = formatException(exc)
elif theFmt == self.FMT_HTM: elif theFmt == self.FMT_HTM:
makeHtml = ToHtml(self.theProject) makeHtml = ToHtml(self.theProject)
@@ -894,7 +895,7 @@ class GuiBuildNovel(QDialog):
makeHtml.saveHTML5(savePath) makeHtml.saveHTML5(savePath)
wSuccess = True wSuccess = True
except Exception as exc: except Exception as exc:
errMsg = str(exc) errMsg = formatException(exc)
elif theFmt == self.FMT_NWD: elif theFmt == self.FMT_NWD:
makeNwd = ToMarkdown(self.theProject) makeNwd = ToMarkdown(self.theProject)
@@ -907,7 +908,7 @@ class GuiBuildNovel(QDialog):
makeNwd.saveRawMarkdown(savePath) makeNwd.saveRawMarkdown(savePath)
wSuccess = True wSuccess = True
except Exception as exc: except Exception as exc:
errMsg = str(exc) errMsg = formatException(exc)
elif theFmt in (self.FMT_MD, self.FMT_GH): elif theFmt in (self.FMT_MD, self.FMT_GH):
makeMd = ToMarkdown(self.theProject) makeMd = ToMarkdown(self.theProject)
@@ -924,7 +925,7 @@ class GuiBuildNovel(QDialog):
makeMd.saveMarkdown(savePath) makeMd.saveMarkdown(savePath)
wSuccess = True wSuccess = True
except Exception as exc: except Exception as exc:
errMsg = str(exc) errMsg = formatException(exc)
elif theFmt == self.FMT_JSON_H or theFmt == self.FMT_JSON_M: elif theFmt == self.FMT_JSON_H or theFmt == self.FMT_JSON_M:
jsonData = { jsonData = {
@@ -969,7 +970,7 @@ class GuiBuildNovel(QDialog):
outFile.write(json.dumps(jsonData, indent=2)) outFile.write(json.dumps(jsonData, indent=2))
wSuccess = True wSuccess = True
except Exception as exc: except Exception as exc:
errMsg = str(exc) errMsg = formatException(exc)
elif theFmt == self.FMT_PDF: elif theFmt == self.FMT_PDF:
try: try:
@@ -984,7 +985,7 @@ class GuiBuildNovel(QDialog):
wSuccess = True wSuccess = True
except Exception as exc: except Exception as exc:
errMsg = str(exc) errMsg = formatException(exc)
else: else:
# If the if statements above and here match, it should not # If the if statements above and here match, it should not
@@ -1050,7 +1051,7 @@ class GuiBuildNovel(QDialog):
theData = json.loads(theJson) theData = json.loads(theJson)
except Exception: except Exception:
logger.error("Failed to load build cache") logger.error("Failed to load build cache")
novelwriter.logException() logException()
return False return False
if "buildTime" in theData.keys(): if "buildTime" in theData.keys():
@@ -1078,7 +1079,7 @@ class GuiBuildNovel(QDialog):
}, indent=2)) }, indent=2))
except Exception: except Exception:
logger.error("Failed to save build cache") logger.error("Failed to save build cache")
novelwriter.logException() logException()
return False return False
return True return True
@@ -1302,9 +1303,12 @@ class GuiBuildNovelDocView(QTextBrowser):
return return
def setStyleSheet(self, theStyles=[]): def setStyleSheet(self, theStyles=None):
"""Set the stylesheet for the preview document. """Set the stylesheet for the preview document.
""" """
if theStyles is None:
theStyles = []
if not theStyles: if not theStyles:
theStyles.append("h1, h2 {color: rgb(66, 113, 174);}") theStyles.append("h1, h2 {color: rgb(66, 113, 174);}")
theStyles.append("h3, h4 {color: rgb(50, 50, 50);}") theStyles.append("h3, h4 {color: rgb(50, 50, 50);}")
+5 -4
View File
@@ -38,6 +38,7 @@ from PyQt5.QtWidgets import (
) )
from novelwriter.enum import nwAlert from novelwriter.enum import nwAlert
from novelwriter.error import formatException
from novelwriter.common import formatTime, checkInt, checkIntRange, checkIntTuple from novelwriter.common import formatTime, checkInt, checkIntRange, checkIntTuple
from novelwriter.constants import nwConst, nwFiles from novelwriter.constants import nwConst, nwFiles
from novelwriter.gui.custom import QSwitch from novelwriter.gui.custom import QSwitch
@@ -404,7 +405,7 @@ class GuiWritingStats(QDialog):
wSuccess = True wSuccess = True
except Exception as exc: except Exception as exc:
errMsg = str(exc) errMsg = formatException(exc)
wSuccess = False wSuccess = False
# Report to user # Report to user
@@ -480,9 +481,9 @@ class GuiWritingStats(QDialog):
self.logData.append((dStart, sDiff, wcNovel, wcNotes, sIdle)) self.logData.append((dStart, sDiff, wcNovel, wcNotes, sIdle))
except Exception as exc: except Exception as exc:
self.theParent.makeAlert([ self.theParent.makeAlert(self.tr(
self.tr("Failed to read session log file."), str(exc) "Failed to read session log file."
], nwAlert.ERROR) ), nwAlert.ERROR, exception=exc)
return False return False
ttWords = ttNovel + ttNotes ttWords = ttNovel + ttNotes
+2 -2
View File
@@ -113,8 +113,8 @@ class MockApp:
# =========================================================================== # # =========================================================================== #
def causeOSError(*args, **kwargs): def causeOSError(*args, **kwargs):
raise OSError("OSError") raise OSError("Mock OSError")
def causeException(*args, **kwargs): def causeException(*args, **kwargs):
raise Exception("Exception") raise Exception("Mock Exception")
+3 -3
View File
@@ -56,7 +56,7 @@ def testCoreDocument_LoadSave(monkeypatch, mockGUI, nwMinimal):
mp.setattr("builtins.open", causeOSError) mp.setattr("builtins.open", causeOSError)
theDoc = NWDoc(theProject, sHandle) theDoc = NWDoc(theProject, sHandle)
assert theDoc.readDocument() is None assert theDoc.readDocument() is None
assert theDoc.getError() == "OSError" assert theDoc.getError() == "OSError: Mock OSError"
# Load the text # Load the text
theDoc = NWDoc(theProject, sHandle) theDoc = NWDoc(theProject, sHandle)
@@ -107,7 +107,7 @@ def testCoreDocument_LoadSave(monkeypatch, mockGUI, nwMinimal):
with monkeypatch.context() as mp: with monkeypatch.context() as mp:
mp.setattr("builtins.open", causeOSError) mp.setattr("builtins.open", causeOSError)
assert theDoc.writeDocument(theText) is False assert theDoc.writeDocument(theText) is False
assert theDoc.getError() == "OSError" assert theDoc.getError() == "OSError: Mock OSError"
# Saving with no handle # Saving with no handle
theDoc._docHandle = None theDoc._docHandle = None
@@ -126,7 +126,7 @@ def testCoreDocument_LoadSave(monkeypatch, mockGUI, nwMinimal):
mp.setattr("os.unlink", causeOSError) mp.setattr("os.unlink", causeOSError)
theDoc = NWDoc(theProject, xHandle) theDoc = NWDoc(theProject, xHandle)
assert theDoc.deleteDocument() is False assert theDoc.deleteDocument() is False
assert theDoc.getError() == "OSError" assert theDoc.getError() == "OSError: Mock OSError"
# Make the delete pass # Make the delete pass
theDoc = NWDoc(theProject, xHandle) theDoc = NWDoc(theProject, xHandle)