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:
committed by
GitHub
parent
67d2e266fd
commit
00eea24e3f
@@ -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):
|
||||||
|
|||||||
@@ -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:"):
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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
@@ -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);}")
|
||||||
|
|||||||
@@ -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
@@ -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")
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user