Fix some typing issues

This commit is contained in:
Veronica Berglyd Olsen
2023-06-04 00:40:04 +02:00
parent 135ba3f290
commit 5f6335d8f9
7 changed files with 95 additions and 90 deletions
+50 -58
View File
@@ -29,13 +29,13 @@ import hashlib
import logging
import xml.etree.ElementTree as ET
from typing import Any
from typing import Any, Literal
from pathlib import Path
from datetime import datetime
from configparser import ConfigParser
from PyQt5.QtCore import QCoreApplication
from PyQt5.QtWidgets import qApp
from PyQt5.QtWidgets import QWidget, qApp
from novelwriter.enum import nwItemClass, nwItemType, nwItemLayout
from novelwriter.error import logException
@@ -113,14 +113,14 @@ def checkHandle(value, default, allowNone=False):
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:
return str(uuid.UUID(value))
except Exception:
return default
def checkPath(value, default):
def checkPath(value: Any, default: Path) -> Path:
"""Check if a value is a valid path. Non-empty strings are accepted.
"""
if isinstance(value, Path):
@@ -135,7 +135,7 @@ def checkPath(value, default):
# Validator Functions
# =============================================================================================== #
def isHandle(value):
def isHandle(value: Any) -> bool:
"""Check if a string is a valid novelWriter handle.
Note: This is case sensitive. Must be lower case!
"""
@@ -149,9 +149,8 @@ def isHandle(value):
return True
def isTitleTag(value):
"""Check if a string is a valid title tag string.
"""
def isTitleTag(value: Any) -> bool:
"""Check if a string is a valid title tag string."""
if not isinstance(value, str):
return False
if len(value) != 5:
@@ -164,27 +163,23 @@ def isTitleTag(value):
return True
def isItemClass(value):
"""Check if a string is a valid nwItemClass identifier.
"""
def isItemClass(value: str) -> bool:
"""Check if a string is a valid nwItemClass identifier."""
return value in nwItemClass.__members__
def isItemType(value):
"""Check if a string is a valid nwItemType identifier.
"""
def isItemType(value: str) -> bool:
"""Check if a string is a valid nwItemType identifier."""
return value in nwItemType.__members__
def isItemLayout(value):
"""Check if a string is a valid nwItemLayout identifier.
"""
def isItemLayout(value: str) -> bool:
"""Check if a string is a valid nwItemLayout identifier."""
return value in nwItemLayout.__members__
def hexToInt(value, default=0):
"""Convert a hex string to an integer.
"""
def hexToInt(value: Any, default: int = 0) -> int:
"""Convert a hex string to an integer."""
if isinstance(value, str):
try:
return int(value, 16)
@@ -193,13 +188,13 @@ def hexToInt(value, default=0):
return default
def minmax(value, minVal, maxVal):
def minmax(value: int, minVal: int, maxVal: int) -> int:
"""Make sure an integer is between min and max value (inclusive).
"""
return min(maxVal, max(minVal, value))
def checkIntTuple(value, valid, default):
def checkIntTuple(value: int, valid: tuple | list | set, default: int) -> int:
"""Check that an int is an element of a tuple. If it isn't, return
the default value.
"""
@@ -213,7 +208,7 @@ def checkIntTuple(value, valid, default):
# Formatting Functions
# =============================================================================================== #
def formatInt(value):
def formatInt(value: int) -> str:
"""Formats an integer with k, M, G etc.
"""
if not isinstance(value, int):
@@ -260,20 +255,19 @@ def formatTime(t: int) -> str:
# String Functions
# =============================================================================================== #
def simplified(string):
"""Take a string an strip leading and trailing whitespaces, and
def simplified(text: str) -> str:
"""Take a string and strip leading and trailing whitespaces, and
replace all occurences of (multiple) whitespaces with a 0x20 space.
"""
return " ".join(str(string).strip().split())
return " ".join(str(text).strip().split())
def yesNo(value):
"""Convert a boolean evaluated variable to a yes or no.
"""
def yesNo(value: int | bool | None) -> Literal["yes", "no"]:
"""Convert a boolean evaluated variable to a yes or no."""
return "yes" if value else "no"
def transferCase(source, target):
def transferCase(source: str, target: str) -> str:
"""Transfers the case of the source word to the target word. This
will consider all upper or lower, and first char capitalisation.
"""
@@ -295,7 +289,7 @@ def transferCase(source, target):
return theResult
def fuzzyTime(seconds):
def fuzzyTime(seconds: int) -> str:
"""Converts a time difference in seconds into a fuzzy time string.
"""
if seconds < 0:
@@ -356,7 +350,7 @@ def fuzzyTime(seconds):
).format(int(round(seconds/31557600)))
def numberToRoman(value, toLower=False):
def numberToRoman(value: int, toLower: bool = False) -> str:
"""Convert an integer to a Roman number.
"""
if not isinstance(value, int):
@@ -384,7 +378,7 @@ def numberToRoman(value, toLower=False):
# Encoder Functions
# =============================================================================================== #
def jsonEncode(data, n=0, nmax=0):
def jsonEncode(data: dict | list | tuple, n: int = 0, nmax: int = 0) -> str:
"""Encode a dictionary, list or tuple as a json object or array, and
indent from level n up to a max level nmax if nmax is larger than 0.
"""
@@ -474,7 +468,7 @@ def xmlIndent(tree: ET.Element | ET.ElementTree):
# File and File System Functions
# =============================================================================================== #
def readTextFile(path):
def readTextFile(path: str | Path) -> str:
"""Read the content of a text file in a robust manner.
"""
path = Path(path)
@@ -488,7 +482,7 @@ def readTextFile(path):
return ""
def makeFileNameSafe(value):
def makeFileNameSafe(value: str) -> str:
"""Returns a filename safe string of the value.
"""
clean = ""
@@ -498,7 +492,7 @@ def makeFileNameSafe(value):
return clean
def sha256sum(path):
def sha256sum(path: str | Path) -> str | None:
"""Make a shasum of a file using a buffer.
Based on: https://stackoverflow.com/a/44873382/5825851
"""
@@ -521,7 +515,7 @@ def sha256sum(path):
# Other Functions
# =============================================================================================== #
def getGuiItem(objName):
def getGuiItem(objName: str) -> QWidget | None:
"""Returns a QtWidget based on its objectName.
"""
for qWidget in qApp.topLevelWidgets():
@@ -535,50 +529,49 @@ def getGuiItem(objName):
# =============================================================================================== #
class NWConfigParser(ConfigParser):
"""Common: Adapted Config Parser
This is a subclass of the standard config parser that adds type safe
helper functions, and support for lists.
"""
def __init__(self):
super().__init__()
def rdStr(self, section, option, default):
"""Read string value.
"""
def rdStr(self, section: str, option: str, default: str) -> str:
"""Read string value."""
return self.get(section, option, fallback=default)
def rdInt(self, section, option, default):
"""Read integer value.
"""
def rdInt(self, section: str, option: str, default: int) -> int:
"""Read integer value."""
try:
return self.getint(section, option, fallback=default)
except ValueError:
logger.error("Could not read '%s':'%s' from config", section, option)
return default
def rdFlt(self, section, option, default):
"""Read float value.
"""
def rdFlt(self, section: str, option: str, default: float) -> float:
"""Read float value."""
try:
return self.getfloat(section, option, fallback=default)
except ValueError:
logger.error("Could not read '%s':'%s' from config", section, option)
return default
def rdBool(self, section, option, default):
"""Read boolean value.
"""
def rdBool(self, section: str, option: str, default: bool) -> bool:
"""Read boolean value."""
try:
return self.getboolean(section, option, fallback=default)
except ValueError:
logger.error("Could not read '%s':'%s' from config", section, option)
return default
def rdPath(self, section, option, default):
"""Read a path value.
"""
def rdPath(self, section: str, option: str, default: Path) -> Path:
"""Read a Path value."""
return checkPath(self.get(section, option, fallback=default), default)
def rdStrList(self, section, option, default):
"""Read string list.
"""
def rdStrList(self, section: str, option: str, default: list[str]) -> list[str]:
"""Read string list."""
result = default.copy() if isinstance(default, list) else []
if self.has_option(section, option):
data = self.get(section, option, fallback="").split(",")
@@ -586,9 +579,8 @@ class NWConfigParser(ConfigParser):
result[i] = data[i].strip()
return result
def rdIntList(self, section, option, default):
"""Read integer list.
"""
def rdIntList(self, section: str, option: str, default: list[int]) -> list[int]:
"""Read integer list."""
result = default.copy() if isinstance(default, list) else []
if self.has_option(section, option):
data = self.get(section, option, fallback="").split(",")