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