diff --git a/novelwriter/common.py b/novelwriter/common.py index cdb10278..b658cf6d 100644 --- a/novelwriter/common.py +++ b/novelwriter/common.py @@ -29,7 +29,7 @@ import logging import unicodedata import xml.etree.ElementTree as ET -from typing import Any, Literal +from typing import TYPE_CHECKING, Any, Literal from pathlib import Path from datetime import datetime from configparser import ConfigParser @@ -43,6 +43,9 @@ from novelwriter.enum import nwItemClass, nwItemType, nwItemLayout from novelwriter.error import logException from novelwriter.constants import nwConst, nwUnicode +if TYPE_CHECKING: # pragma: no cover + from typing import TypeGuard # Requires Python 3.10 + logger = logging.getLogger(__name__) @@ -104,15 +107,6 @@ def checkBool(value: Any, default: bool) -> bool: 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: """Try to process a value as an UUID, or return a default.""" try: @@ -135,7 +129,7 @@ def checkPath(value: Any, default: Path) -> Path: # Validator Functions ## -def isHandle(value: Any) -> bool: +def isHandle(value: Any) -> TypeGuard[str]: """Check if a string is a valid novelWriter handle. Note: This is case sensitive. Must be lower case! """ @@ -149,7 +143,7 @@ def isHandle(value: Any) -> bool: return True -def isTitleTag(value: Any) -> bool: +def isTitleTag(value: Any) -> TypeGuard[str]: """Check if a string is a valid title tag string.""" if not isinstance(value, str): return False @@ -163,19 +157,19 @@ def isTitleTag(value: Any) -> bool: return True -def isItemClass(value: str) -> bool: +def isItemClass(value: Any) -> TypeGuard[str]: """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.""" - 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.""" - return value in nwItemLayout.__members__ + return isinstance(value, str) and value in nwItemLayout.__members__ 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: - """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)) diff --git a/tests/test_base/test_base_common.py b/tests/test_base/test_base_common.py index a45571cf..f074be0f 100644 --- a/tests/test_base/test_base_common.py +++ b/tests/test_base/test_base_common.py @@ -33,9 +33,9 @@ from PyQt5.QtGui import QDesktopServices from PyQt5.QtCore import QUrl from novelwriter.common import ( - checkBool, checkFloat, checkHandle, checkInt, checkIntTuple, checkPath, - checkString, checkStringNone, checkUuid, formatInt, formatTime, - formatTimeStamp, formatVersion, fuzzyTime, getFileSize, hexToInt, isHandle, isItemClass, + checkBool, checkFloat, checkInt, checkIntTuple, checkPath, checkString, + checkStringNone, checkUuid, formatInt, formatTime, formatTimeStamp, + formatVersion, fuzzyTime, getFileSize, hexToInt, isHandle, isItemClass, isItemLayout, isItemType, isTitleTag, jsonEncode, makeFileNameSafe, minmax, numberToRoman, NWConfigParser, openExternalPath, readTextFile, simplified, transferCase, xmlIndent, yesNo @@ -151,19 +151,6 @@ def 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 def testBaseCommon_checkUuid(): """Test the checkUuid function.""" @@ -236,7 +223,7 @@ def testBaseCommon_isItemClass(): # Invalid assert isItemClass("None") is False - assert isItemClass(None) is False # type: ignore + assert isItemClass(None) is False assert isItemClass("STUFF") is False # END Test testBaseCommon_isItemClass