Clean up common module, and fix a few typing issues (#1188)

This commit is contained in:
Veronica Berglyd Olsen
2022-10-19 00:18:07 +02:00
committed by GitHub
7 changed files with 102 additions and 123 deletions
+21 -30
View File
@@ -45,52 +45,54 @@ logger = logging.getLogger(__name__)
# Checker Functions # Checker Functions
# =============================================================================================== # # =============================================================================================== #
def checkString(value, default, allowNone=False): def checkStringNone(value, default):
"""Check if a variable is a string or a None. """Check if a variable is a string or a None.
""" """
if allowNone and (value is None or value == "None"): if value is None or value == "None":
return None return None
if isinstance(value, str): if isinstance(value, str):
return str(value) return str(value)
return default return default
def checkInt(value, default, allowNone=False): def checkString(value, default):
"""Check if a variable is an integer or a None. """Check if a variable is a string.
"""
if isinstance(value, str):
return str(value)
return default
def checkInt(value, default):
"""Check if a variable is an integer.
""" """
if allowNone and (value is None or value == "None"):
return None
try: try:
return int(value) return int(value)
except Exception: except Exception:
return default return default
def checkFloat(value, default, allowNone=False): def checkFloat(value, default):
"""Check if a variable is a float or a None. """Check if a variable is a float.
""" """
if allowNone and (value is None or value == "None"):
return None
try: try:
return float(value) return float(value)
except Exception: except Exception:
return default return default
def checkBool(value, default, allowNone=False): def checkBool(value, default):
"""Check if a variable is a boolean or a None. """Check if a variable is a boolean.
""" """
if allowNone and (value is None or value == "None"): if isinstance(value, bool):
return None return value
elif isinstance(value, str):
if isinstance(value, str):
if value == "True": if value == "True":
return True return True
elif value == "False": elif value == "False":
return False return False
else: else:
return default return default
elif isinstance(value, int): elif isinstance(value, int):
if value == 1: if value == 1:
return True return True
@@ -98,7 +100,6 @@ def checkBool(value, default, allowNone=False):
return False return False
else: else:
return default return default
return default return default
@@ -174,16 +175,6 @@ def hexToInt(value, default=0):
return default return default
def checkIntRange(value, first, last, default):
"""Check that an int is in a given range. If it isn't, return the
default value.
"""
if isinstance(value, int):
if value >= first and value <= last:
return value
return default
def minmax(value, minVal, maxVal): def minmax(value, minVal, maxVal):
"""Make sure an integer is between min and max value (inclusive). """Make sure an integer is between min and max value (inclusive).
""" """
@@ -263,7 +254,7 @@ def splitVersionNumber(value):
and patch, and computes an integer value aabbcc. and patch, and computes an integer value aabbcc.
""" """
if not isinstance(value, str): if not isinstance(value, str):
return [0, 0, 0, 0] return 0, 0, 0, 0
vMajor = 0 vMajor = 0
vMinor = 0 vMinor = 0
@@ -282,7 +273,7 @@ def splitVersionNumber(value):
vInt = vMajor*10000 + vMinor*100 + vPatch vInt = vMajor*10000 + vMinor*100 + vPatch
return [vMajor, vMinor, vPatch, vInt] return vMajor, vMinor, vPatch, vInt
def transferCase(theSource, theTarget): def transferCase(theSource, theTarget):
+3 -9
View File
@@ -668,23 +668,17 @@ class TagsIndex:
def tagHandle(self, tagKey): def tagHandle(self, tagKey):
"""Get the handle of a given tag. """Get the handle of a given tag.
""" """
if tagKey in self._tags: return self._tags.get(tagKey, {}).get("handle", None)
return self._tags.get(tagKey).get("handle")
return None
def tagHeading(self, tagKey): def tagHeading(self, tagKey):
"""Get the heading of a given tag. """Get the heading of a given tag.
""" """
if tagKey in self._tags: return self._tags.get(tagKey, {}).get("heading", nwHeaders.TT_NONE)
return self._tags.get(tagKey).get("heading")
return nwHeaders.TT_NONE
def tagClass(self, tagKey): def tagClass(self, tagKey):
"""Get the class of a given tag. """Get the class of a given tag.
""" """
if tagKey in self._tags: return self._tags.get(tagKey, {}).get("class", None)
return self._tags.get(tagKey).get("class")
return None
## ##
# Pack/Unpack # Pack/Unpack
+1 -2
View File
@@ -188,8 +188,7 @@ class OptionState:
the default value. the default value.
""" """
if group in self._theState: if group in self._theState:
if name in self._theState[group]: return checkBool(self._theState[group].get(name, default), default)
return checkBool(self._theState[group].get(name, default), default)
return default return default
def getEnum(self, group, name, lookup, default): def getEnum(self, group, name, lookup, default):
+18 -18
View File
@@ -44,7 +44,7 @@ from novelwriter.core.document import NWDoc
from novelwriter.enum import nwItemType, nwItemClass, nwItemLayout, nwAlert from novelwriter.enum import nwItemType, nwItemClass, nwItemLayout, nwAlert
from novelwriter.error import logException from novelwriter.error import logException
from novelwriter.common import ( from novelwriter.common import (
checkString, checkBool, checkInt, isHandle, formatTimeStamp, checkString, checkBool, checkInt, checkStringNone, isHandle, formatTimeStamp,
makeFileNameSafe, hexToInt, minmax, simplified makeFileNameSafe, hexToInt, minmax, simplified
) )
from novelwriter.constants import trConst, nwFiles, nwLabels from novelwriter.constants import trConst, nwFiles, nwLabels
@@ -187,7 +187,7 @@ class NWProject:
return False return False
newDoc = NWDoc(self, tHandle) newDoc = NWDoc(self, tHandle)
if newDoc.readDocument().strip(): if (newDoc.readDocument() or "").strip():
return False return False
hshText = "#"*minmax(hLevel, 1, 4) hshText = "#"*minmax(hLevel, 1, 4)
@@ -593,13 +593,13 @@ class NWProject:
if xItem.text is None: if xItem.text is None:
continue continue
if xItem.tag == "name": if xItem.tag == "name":
self.projName = checkString(simplified(xItem.text), "") self.projName = simplified(checkString(xItem.text, ""))
logger.verbose("Working Title: '%s'", self.projName) logger.verbose("Working Title: '%s'", self.projName)
elif xItem.tag == "title": elif xItem.tag == "title":
self.bookTitle = checkString(simplified(xItem.text), "") self.bookTitle = simplified(checkString(xItem.text, ""))
logger.verbose("Title is '%s'", self.bookTitle) logger.verbose("Title is '%s'", self.bookTitle)
elif xItem.tag == "author": elif xItem.tag == "author":
author = checkString(simplified(xItem.text), "") author = simplified(checkString(xItem.text, ""))
if author: if author:
self.bookAuthors.append(author) self.bookAuthors.append(author)
logger.verbose("Author: '%s'", author) logger.verbose("Author: '%s'", author)
@@ -618,25 +618,25 @@ class NWProject:
if xItem.tag == "doBackup": if xItem.tag == "doBackup":
self.doBackup = checkBool(xItem.text, False) self.doBackup = checkBool(xItem.text, False)
elif xItem.tag == "language": elif xItem.tag == "language":
self.projLang = checkString(xItem.text, None, True) self.projLang = checkStringNone(xItem.text, None)
elif xItem.tag == "spellCheck": elif xItem.tag == "spellCheck":
self.spellCheck = checkBool(xItem.text, False) self.spellCheck = checkBool(xItem.text, False)
elif xItem.tag == "spellLang": elif xItem.tag == "spellLang":
self.projSpell = checkString(xItem.text, None, True) self.projSpell = checkStringNone(xItem.text, None)
elif xItem.tag == "lastEdited": elif xItem.tag == "lastEdited":
self.lastEdited = checkString(xItem.text, None, True) self.lastEdited = checkStringNone(xItem.text, None)
elif xItem.tag == "lastViewed": elif xItem.tag == "lastViewed":
self.lastViewed = checkString(xItem.text, None, True) self.lastViewed = checkStringNone(xItem.text, None)
elif xItem.tag == "lastNovel": elif xItem.tag == "lastNovel":
self.lastNovel = checkString(xItem.text, None, True) self.lastNovel = checkStringNone(xItem.text, None)
elif xItem.tag == "lastOutline": elif xItem.tag == "lastOutline":
self.lastOutline = checkString(xItem.text, None, True) self.lastOutline = checkStringNone(xItem.text, None)
elif xItem.tag == "lastWordCount": elif xItem.tag == "lastWordCount":
self.lastWCount = checkInt(xItem.text, 0, False) self.lastWCount = checkInt(xItem.text, 0)
elif xItem.tag == "novelWordCount": elif xItem.tag == "novelWordCount":
self.lastNovelWC = checkInt(xItem.text, 0, False) self.lastNovelWC = checkInt(xItem.text, 0)
elif xItem.tag == "notesWordCount": elif xItem.tag == "notesWordCount":
self.lastNotesWC = checkInt(xItem.text, 0, False) self.lastNotesWC = checkInt(xItem.text, 0)
elif xItem.tag == "status": elif xItem.tag == "status":
self.statusItems.unpackXML(xItem) self.statusItems.unpackXML(xItem)
elif xItem.tag == "importance": elif xItem.tag == "importance":
@@ -645,12 +645,12 @@ class NWProject:
for xEntry in xItem: for xEntry in xItem:
if xEntry.tag == "entry" and "key" in xEntry.attrib: if xEntry.tag == "entry" and "key" in xEntry.attrib:
self.autoReplace[xEntry.attrib["key"]] = checkString( self.autoReplace[xEntry.attrib["key"]] = checkString(
xEntry.text, None, False xEntry.text, "ERROR"
) )
elif xItem.tag == "titleFormat": elif xItem.tag == "titleFormat":
titleFormat = self.titleFormat.copy() titleFormat = self.titleFormat.copy()
for xEntry in xItem: for xEntry in xItem:
titleFormat[xEntry.tag] = checkString(xEntry.text, "", False) titleFormat[xEntry.tag] = checkString(xEntry.text, "")
self.setTitleFormat(titleFormat) self.setTitleFormat(titleFormat)
elif xChild.tag == "content": elif xChild.tag == "content":
@@ -1091,7 +1091,7 @@ class NWProject:
def setSpellLang(self, theLang): def setSpellLang(self, theLang):
"""Set the project-specific spell check language. """Set the project-specific spell check language.
""" """
theLang = checkString(theLang, None, True) theLang = checkStringNone(theLang, None)
if self.projSpell != theLang: if self.projSpell != theLang:
self.projSpell = theLang self.projSpell = theLang
self.setProjectChanged(True) self.setProjectChanged(True)
@@ -1101,7 +1101,7 @@ class NWProject:
def setProjectLang(self, theLang): def setProjectLang(self, theLang):
"""Set the project-specific language. """Set the project-specific language.
""" """
theLang = checkString(theLang, None, True) theLang = checkStringNone(theLang, None)
if self.projLang != theLang: if self.projLang != theLang:
self.projLang = theLang self.projLang = theLang
self._loadProjectLocalisation() self._loadProjectLocalisation()
+4 -10
View File
@@ -304,16 +304,10 @@ class Tokenizer(ABC):
if self._theItem is None: if self._theItem is None:
return False return False
self._theText = "" if theText is None:
if theText is not None: theText = NWDoc(self.theProject, theHandle).readDocument() or ""
# If the text is set, just use that
self._theText = theText self._theText = theText
else:
# Otherwise, load it from file
theDoc = NWDoc(self.theProject, theHandle)
theText = theDoc.readDocument()
if theText:
self._theText = theText
docSize = len(self._theText) docSize = len(self._theText)
if docSize > nwConst.MAX_DOCSIZE: if docSize > nwConst.MAX_DOCSIZE:
+2 -2
View File
@@ -39,7 +39,7 @@ from PyQt5.QtWidgets import (
from novelwriter.enum import nwAlert from novelwriter.enum import nwAlert
from novelwriter.error import formatException from novelwriter.error import formatException
from novelwriter.common import formatTime, checkInt, checkIntRange, checkIntTuple from novelwriter.common import formatTime, checkInt, checkIntTuple, minmax
from novelwriter.custom import QSwitch from novelwriter.custom import QSwitch
from novelwriter.constants import nwConst, nwFiles from novelwriter.constants import nwConst, nwFiles
@@ -116,7 +116,7 @@ class GuiWritingStats(QDialog):
hHeader.setTextAlignment(self.C_IDLE, Qt.AlignRight) hHeader.setTextAlignment(self.C_IDLE, Qt.AlignRight)
hHeader.setTextAlignment(self.C_COUNT, Qt.AlignRight) hHeader.setTextAlignment(self.C_COUNT, Qt.AlignRight)
sortCol = checkIntRange(pOptions.getInt("GuiWritingStats", "sortCol", 0), 0, 2, 0) sortCol = minmax(pOptions.getInt("GuiWritingStats", "sortCol", 0), 0, 2)
sortOrder = checkIntTuple( sortOrder = checkIntTuple(
pOptions.getInt("GuiWritingStats", "sortOrder", Qt.DescendingOrder), pOptions.getInt("GuiWritingStats", "sortOrder", Qt.DescendingOrder),
(Qt.AscendingOrder, Qt.DescendingOrder), Qt.DescendingOrder (Qt.AscendingOrder, Qt.DescendingOrder), Qt.DescendingOrder
+53 -52
View File
@@ -29,8 +29,8 @@ from tools import writeFile
from novelwriter.guimain import GuiMain from novelwriter.guimain import GuiMain
from novelwriter.common import ( from novelwriter.common import (
checkString, checkInt, checkFloat, checkBool, checkHandle, isHandle, checkStringNone, checkString, checkInt, checkFloat, checkBool, checkHandle,
isTitleTag, isItemClass, isItemType, isItemLayout, hexToInt, checkIntRange, isHandle, isTitleTag, isItemClass, isItemType, isItemLayout, hexToInt,
minmax, checkIntTuple, formatInt, formatTimeStamp, formatTime, simplified, minmax, checkIntTuple, formatInt, formatTimeStamp, formatTime, simplified,
splitVersionNumber, transferCase, fuzzyTime, numberToRoman, jsonEncode, splitVersionNumber, transferCase, fuzzyTime, numberToRoman, jsonEncode,
readTextFile, makeFileNameSafe, ensureFolder, sha256sum, getGuiItem, readTextFile, makeFileNameSafe, ensureFolder, sha256sum, getGuiItem,
@@ -38,17 +38,29 @@ from novelwriter.common import (
) )
@pytest.mark.base
def testBaseCommon_CheckStringNone():
"""Test the checkStringNone function.
"""
assert checkStringNone("Stuff", "NotNone") == "Stuff"
assert checkStringNone("None", "NotNone") is None
assert checkStringNone(None, "NotNone") is None
assert checkStringNone(1, "NotNone") == "NotNone"
assert checkStringNone(1.0, "NotNone") == "NotNone"
assert checkStringNone(True, "NotNone") == "NotNone"
# END Test testBaseCommon_CheckStringNone
@pytest.mark.base @pytest.mark.base
def testBaseCommon_CheckString(): def testBaseCommon_CheckString():
"""Test the checkString function. """Test the checkString function.
""" """
assert checkString(None, "NotNone", True) is None assert checkString("None", "NotNone") == "None"
assert checkString("None", "NotNone", True) is None assert checkString(None, "NotNone") == "NotNone"
assert checkString("None", "NotNone", False) == "None" assert checkString(1, "NotNone") == "NotNone"
assert checkString(None, "NotNone", False) == "NotNone" assert checkString(1.0, "NotNone") == "NotNone"
assert checkString(1, "NotNone", False) == "NotNone" assert checkString(True, "NotNone") == "NotNone"
assert checkString(1.0, "NotNone", False) == "NotNone"
assert checkString(True, "NotNone", False) == "NotNone"
# END Test testBaseCommon_CheckString # END Test testBaseCommon_CheckString
@@ -57,12 +69,12 @@ def testBaseCommon_CheckString():
def testBaseCommon_CheckInt(): def testBaseCommon_CheckInt():
"""Test the checkInt function. """Test the checkInt function.
""" """
assert checkInt(None, 3, True) is None assert checkInt(None, 3) == 3
assert checkInt("None", 3, True) is None assert checkInt("1", 3) == 1
assert checkInt(None, 3, False) == 3 assert checkInt("1.0", 3) == 3
assert checkInt(1, 3, False) == 1 assert checkInt(1, 3) == 1
assert checkInt(1.0, 3, False) == 1 assert checkInt(1.0, 3) == 1
assert checkInt(True, 3, False) == 1 assert checkInt(True, 3) == 1
# END Test testBaseCommon_CheckInt # END Test testBaseCommon_CheckInt
@@ -71,12 +83,12 @@ def testBaseCommon_CheckInt():
def testBaseCommon_CheckFloat(): def testBaseCommon_CheckFloat():
"""Test the checkFloat function. """Test the checkFloat function.
""" """
assert checkFloat(None, 3.0, True) is None assert checkFloat(None, 3.0) == 3.0
assert checkFloat("None", 3.0, True) is None assert checkFloat("1", 3.0) == 1.0
assert checkFloat(None, 3.0, False) == 3.0 assert checkFloat("1.0", 3.0) == 1.0
assert checkFloat(1, 3.0, False) == 1.0 assert checkFloat(1, 3.0) == 1.0
assert checkFloat(1.0, 3.0, False) == 1.0 assert checkFloat(1.0, 3.0) == 1.0
assert checkFloat(True, 3.0, False) == 1.0 assert checkFloat(True, 3.0) == 1.0
# END Test testBaseCommon_CheckInt # END Test testBaseCommon_CheckInt
@@ -85,17 +97,18 @@ def testBaseCommon_CheckFloat():
def testBaseCommon_CheckBool(): def testBaseCommon_CheckBool():
"""Test the checkBool function. """Test the checkBool function.
""" """
assert checkBool(None, 3, True) is None assert checkBool("True", False) is True
assert checkBool("None", 3, True) is None assert checkBool("False", True) is False
assert checkBool("True", False, False) is True assert checkBool("Boo", False) is False
assert checkBool("False", True, False) is False assert checkBool("Boo", True) is True
assert checkBool("Boo", None, False) is None assert checkBool(0, True) is False
assert checkBool(0, None, False) is False assert checkBool(1, False) is True
assert checkBool(1, None, False) is True assert checkBool(2, True) is True
assert checkBool(2, None, False) is None assert checkBool(2, False) is False
assert checkBool(0.0, None, False) is None assert checkBool(0.0, True) is True
assert checkBool(1.0, None, False) is None assert checkBool(1.0, False) is False
assert checkBool(2.0, None, False) is None assert checkBool(2.0, True) is True
assert checkBool(2.0, False) is False
# END Test testBaseCommon_CheckBool # END Test testBaseCommon_CheckBool
@@ -229,18 +242,6 @@ def testBaseCommon_HexToInt():
# END Test testBaseCommon_HexToInt # END Test testBaseCommon_HexToInt
@pytest.mark.base
def testBaseCommon_CheckIntRange():
"""Test the checkIntRange function.
"""
assert checkIntRange(5, 0, 9, 3) == 5
assert checkIntRange(5, 0, 4, 3) == 3
assert checkIntRange(5, 0, 5, 3) == 5
assert checkIntRange(0, 0, 5, 3) == 0
# END Test testBaseCommon_CheckIntRange
@pytest.mark.base @pytest.mark.base
def testBaseCommon_MinMax(): def testBaseCommon_MinMax():
"""Test the minmax function. """Test the minmax function.
@@ -311,16 +312,16 @@ def testBaseCommon_SplitVersionNumber():
"""Test the splitVersionNumber function. """Test the splitVersionNumber function.
""" """
# OK Values # OK Values
assert splitVersionNumber("1") == [1, 0, 0, 10000] assert splitVersionNumber("1") == (1, 0, 0, 10000)
assert splitVersionNumber("1.2") == [1, 2, 0, 10200] assert splitVersionNumber("1.2") == (1, 2, 0, 10200)
assert splitVersionNumber("1.2.3") == [1, 2, 3, 10203] assert splitVersionNumber("1.2.3") == (1, 2, 3, 10203)
assert splitVersionNumber("1.2.3.4") == [1, 2, 3, 10203] assert splitVersionNumber("1.2.3.4") == (1, 2, 3, 10203)
assert splitVersionNumber("99.99.99") == [99, 99, 99, 999999] assert splitVersionNumber("99.99.99") == (99, 99, 99, 999999)
# Failed Values # Failed Values
assert splitVersionNumber(None) == [0, 0, 0, 0] assert splitVersionNumber(None) == (0, 0, 0, 0)
assert splitVersionNumber(1234) == [0, 0, 0, 0] assert splitVersionNumber(1234) == (0, 0, 0, 0)
assert splitVersionNumber("1.2abc") == [1, 0, 0, 10000] assert splitVersionNumber("1.2abc") == (1, 0, 0, 10000)
# END Test testBaseCommon_SplitVersionNumber # END Test testBaseCommon_SplitVersionNumber