Improve type checking in common module, and delete unused function
This commit is contained in:
+13
-20
@@ -29,7 +29,7 @@ import logging
|
|||||||
import unicodedata
|
import unicodedata
|
||||||
import xml.etree.ElementTree as ET
|
import xml.etree.ElementTree as ET
|
||||||
|
|
||||||
from typing import Any, Literal
|
from typing import TYPE_CHECKING, Any, Literal
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from configparser import ConfigParser
|
from configparser import ConfigParser
|
||||||
@@ -43,6 +43,9 @@ from novelwriter.enum import nwItemClass, nwItemType, nwItemLayout
|
|||||||
from novelwriter.error import logException
|
from novelwriter.error import logException
|
||||||
from novelwriter.constants import nwConst, nwUnicode
|
from novelwriter.constants import nwConst, nwUnicode
|
||||||
|
|
||||||
|
if TYPE_CHECKING: # pragma: no cover
|
||||||
|
from typing import TypeGuard # Requires Python 3.10
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@@ -104,15 +107,6 @@ def checkBool(value: Any, default: bool) -> bool:
|
|||||||
return default
|
return default
|
||||||
|
|
||||||
|
|
||||||
def checkHandle(value, default, allowNone=False):
|
|
||||||
"""Check if a value is a handle."""
|
|
||||||
if allowNone and (value is None or value == "None"):
|
|
||||||
return None
|
|
||||||
if isHandle(value):
|
|
||||||
return str(value)
|
|
||||||
return default
|
|
||||||
|
|
||||||
|
|
||||||
def checkUuid(value: Any, default: str) -> str:
|
def checkUuid(value: Any, default: str) -> str:
|
||||||
"""Try to process a value as an UUID, or return a default."""
|
"""Try to process a value as an UUID, or return a default."""
|
||||||
try:
|
try:
|
||||||
@@ -135,7 +129,7 @@ def checkPath(value: Any, default: Path) -> Path:
|
|||||||
# Validator Functions
|
# Validator Functions
|
||||||
##
|
##
|
||||||
|
|
||||||
def isHandle(value: Any) -> bool:
|
def isHandle(value: Any) -> TypeGuard[str]:
|
||||||
"""Check if a string is a valid novelWriter handle.
|
"""Check if a string is a valid novelWriter handle.
|
||||||
Note: This is case sensitive. Must be lower case!
|
Note: This is case sensitive. Must be lower case!
|
||||||
"""
|
"""
|
||||||
@@ -149,7 +143,7 @@ def isHandle(value: Any) -> bool:
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def isTitleTag(value: Any) -> bool:
|
def isTitleTag(value: Any) -> TypeGuard[str]:
|
||||||
"""Check if a string is a valid title tag string."""
|
"""Check if a string is a valid title tag string."""
|
||||||
if not isinstance(value, str):
|
if not isinstance(value, str):
|
||||||
return False
|
return False
|
||||||
@@ -163,19 +157,19 @@ def isTitleTag(value: Any) -> bool:
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def isItemClass(value: str) -> bool:
|
def isItemClass(value: Any) -> TypeGuard[str]:
|
||||||
"""Check if a string is a valid nwItemClass identifier."""
|
"""Check if a string is a valid nwItemClass identifier."""
|
||||||
return value in nwItemClass.__members__
|
return isinstance(value, str) and value in nwItemClass.__members__
|
||||||
|
|
||||||
|
|
||||||
def isItemType(value: str) -> bool:
|
def isItemType(value: Any) -> TypeGuard[str]:
|
||||||
"""Check if a string is a valid nwItemType identifier."""
|
"""Check if a string is a valid nwItemType identifier."""
|
||||||
return value in nwItemType.__members__
|
return isinstance(value, str) and value in nwItemType.__members__
|
||||||
|
|
||||||
|
|
||||||
def isItemLayout(value: str) -> bool:
|
def isItemLayout(value: Any) -> TypeGuard[str]:
|
||||||
"""Check if a string is a valid nwItemLayout identifier."""
|
"""Check if a string is a valid nwItemLayout identifier."""
|
||||||
return value in nwItemLayout.__members__
|
return isinstance(value, str) and value in nwItemLayout.__members__
|
||||||
|
|
||||||
|
|
||||||
def hexToInt(value: Any, default: int = 0) -> int:
|
def hexToInt(value: Any, default: int = 0) -> int:
|
||||||
@@ -189,8 +183,7 @@ def hexToInt(value: Any, default: int = 0) -> int:
|
|||||||
|
|
||||||
|
|
||||||
def minmax(value: int, minVal: int, maxVal: int) -> int:
|
def minmax(value: int, minVal: int, maxVal: int) -> int:
|
||||||
"""Make sure an integer is between min and max value (inclusive).
|
"""Check that an value is between min and max value (inclusive)."""
|
||||||
"""
|
|
||||||
return min(maxVal, max(minVal, value))
|
return min(maxVal, max(minVal, value))
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -33,9 +33,9 @@ from PyQt5.QtGui import QDesktopServices
|
|||||||
from PyQt5.QtCore import QUrl
|
from PyQt5.QtCore import QUrl
|
||||||
|
|
||||||
from novelwriter.common import (
|
from novelwriter.common import (
|
||||||
checkBool, checkFloat, checkHandle, checkInt, checkIntTuple, checkPath,
|
checkBool, checkFloat, checkInt, checkIntTuple, checkPath, checkString,
|
||||||
checkString, checkStringNone, checkUuid, formatInt, formatTime,
|
checkStringNone, checkUuid, formatInt, formatTime, formatTimeStamp,
|
||||||
formatTimeStamp, formatVersion, fuzzyTime, getFileSize, hexToInt, isHandle, isItemClass,
|
formatVersion, fuzzyTime, getFileSize, hexToInt, isHandle, isItemClass,
|
||||||
isItemLayout, isItemType, isTitleTag, jsonEncode, makeFileNameSafe, minmax,
|
isItemLayout, isItemType, isTitleTag, jsonEncode, makeFileNameSafe, minmax,
|
||||||
numberToRoman, NWConfigParser, openExternalPath, readTextFile, simplified,
|
numberToRoman, NWConfigParser, openExternalPath, readTextFile, simplified,
|
||||||
transferCase, xmlIndent, yesNo
|
transferCase, xmlIndent, yesNo
|
||||||
@@ -151,19 +151,6 @@ def testBaseCommon_checkBool():
|
|||||||
# END Test testBaseCommon_checkBool
|
# END Test testBaseCommon_checkBool
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.base
|
|
||||||
def testBaseCommon_checkHandle():
|
|
||||||
"""Test the checkHandle function."""
|
|
||||||
assert checkHandle("None", 1, True) is None
|
|
||||||
assert checkHandle("None", 1, False) == 1
|
|
||||||
assert checkHandle(None, 1, True) is None
|
|
||||||
assert checkHandle(None, 1, False) == 1
|
|
||||||
assert checkHandle("47666c91c7ccf", None, False) == "47666c91c7ccf"
|
|
||||||
assert checkHandle("h7666c91c7ccf", None, False) is None
|
|
||||||
|
|
||||||
# END Test testBaseCommon_checkHandle
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.base
|
@pytest.mark.base
|
||||||
def testBaseCommon_checkUuid():
|
def testBaseCommon_checkUuid():
|
||||||
"""Test the checkUuid function."""
|
"""Test the checkUuid function."""
|
||||||
@@ -236,7 +223,7 @@ def testBaseCommon_isItemClass():
|
|||||||
|
|
||||||
# Invalid
|
# Invalid
|
||||||
assert isItemClass("None") is False
|
assert isItemClass("None") is False
|
||||||
assert isItemClass(None) is False # type: ignore
|
assert isItemClass(None) is False
|
||||||
assert isItemClass("STUFF") is False
|
assert isItemClass("STUFF") is False
|
||||||
|
|
||||||
# END Test testBaseCommon_isItemClass
|
# END Test testBaseCommon_isItemClass
|
||||||
|
|||||||
Reference in New Issue
Block a user