Add linting of type annotations (#1809)
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
[flake8]
|
[flake8]
|
||||||
ignore = E133,E221,E226,E228,E241,W503
|
ignore = E133,E221,E226,E228,E241,W503,ANN101,ANN102,ANN401
|
||||||
|
per-file-ignores=tests/*:ANN
|
||||||
max-line-length = 99
|
max-line-length = 99
|
||||||
exclude = docs/*
|
exclude = docs/*
|
||||||
|
|||||||
@@ -22,9 +22,9 @@ jobs:
|
|||||||
- name: Checkout Source
|
- name: Checkout Source
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
- name: Install flake8
|
- name: Install flake8
|
||||||
run: pip install flake8 flake8-pep585
|
run: pip install -r requirements-dev.txt
|
||||||
- name: Syntax Check
|
- name: Syntax Check
|
||||||
run: |
|
run: |
|
||||||
flake8 --version
|
flake8 --version
|
||||||
flake8 novelwriter --count --show-source --statistics
|
flake8 novelwriter --count --show-source --statistics
|
||||||
flake8 tests --count --show-source --statistics
|
flake8 tests --count --show-source --statistics --extend-ignore ANN
|
||||||
|
|||||||
+10
-3
@@ -23,16 +23,21 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import sys
|
|
||||||
import getopt
|
import getopt
|
||||||
import logging
|
import logging
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from PyQt5.QtWidgets import QApplication, QErrorMessage
|
from PyQt5.QtWidgets import QApplication, QErrorMessage
|
||||||
|
|
||||||
from novelwriter.error import exceptionHandler, logException
|
|
||||||
from novelwriter.config import Config
|
from novelwriter.config import Config
|
||||||
|
from novelwriter.error import exceptionHandler, logException
|
||||||
from novelwriter.shared import SharedData
|
from novelwriter.shared import SharedData
|
||||||
|
|
||||||
|
if TYPE_CHECKING: # pragma: no cover
|
||||||
|
from novelwriter.guimain import GuiMain
|
||||||
|
|
||||||
# Package Meta
|
# Package Meta
|
||||||
# ============
|
# ============
|
||||||
|
|
||||||
@@ -60,7 +65,7 @@ CONFIG = Config()
|
|||||||
SHARED = SharedData()
|
SHARED = SharedData()
|
||||||
|
|
||||||
|
|
||||||
def main(sysArgs: list | None = None):
|
def main(sysArgs: list | None = None) -> GuiMain | None:
|
||||||
"""Parse command line, set up logging, and launch main GUI."""
|
"""Parse command line, set up logging, and launch main GUI."""
|
||||||
if sysArgs is None:
|
if sysArgs is None:
|
||||||
sysArgs = sys.argv[1:]
|
sysArgs = sys.argv[1:]
|
||||||
@@ -239,4 +244,6 @@ def main(sysArgs: list | None = None):
|
|||||||
|
|
||||||
sys.exit(nwApp.exec())
|
sys.exit(nwApp.exec())
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
# END Function main
|
# END Function main
|
||||||
|
|||||||
@@ -449,7 +449,7 @@ def xmlIndent(tree: ET.Element | ET.ElementTree) -> None:
|
|||||||
|
|
||||||
indentations = ["\n"]
|
indentations = ["\n"]
|
||||||
|
|
||||||
def indentChildren(elem, level):
|
def indentChildren(elem: ET.Element, level: int) -> None:
|
||||||
chLevel = level + 1
|
chLevel = level + 1
|
||||||
try:
|
try:
|
||||||
chIndent = indentations[chLevel]
|
chIndent = indentations[chLevel]
|
||||||
@@ -472,6 +472,8 @@ def xmlIndent(tree: ET.Element | ET.ElementTree) -> None:
|
|||||||
if last is not None:
|
if last is not None:
|
||||||
last.tail = indentations[level]
|
last.tail = indentations[level]
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
if len(tree):
|
if len(tree):
|
||||||
indentChildren(tree, 0)
|
indentChildren(tree, 0)
|
||||||
tree.tail = "\n"
|
tree.tail = "\n"
|
||||||
@@ -534,8 +536,9 @@ class NWConfigParser(ConfigParser):
|
|||||||
helper functions, and support for lists.
|
helper functions, and support for lists.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self) -> None:
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
return
|
||||||
|
|
||||||
def rdStr(self, section: str, option: str, default: str) -> str:
|
def rdStr(self, section: str, option: str, default: str) -> str:
|
||||||
"""Read string value."""
|
"""Read string value."""
|
||||||
|
|||||||
@@ -382,7 +382,7 @@ class BuildSettings:
|
|||||||
|
|
||||||
postponed = []
|
postponed = []
|
||||||
|
|
||||||
def allowRoot(rHandle):
|
def allowRoot(rHandle: str | None) -> None:
|
||||||
if rHandle in postponed and rHandle in result and rHandle is not None:
|
if rHandle in postponed and rHandle in result and rHandle is not None:
|
||||||
result[rHandle] = (True, FilterMode.ROOT)
|
result[rHandle] = (True, FilterMode.ROOT)
|
||||||
postponed.remove(rHandle)
|
postponed.remove(rHandle)
|
||||||
|
|||||||
@@ -449,7 +449,7 @@ class ProjectXMLReader:
|
|||||||
result[xEntry.attrib["key"]] = checkString(xEntry.text, "")
|
result[xEntry.attrib["key"]] = checkString(xEntry.text, "")
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def _parseDictTagText(self, xItem) -> dict:
|
def _parseDictTagText(self, xItem: ET.Element) -> dict:
|
||||||
"""Parse a dictionary stored with key as the tag and the value
|
"""Parse a dictionary stored with key as the tag and the value
|
||||||
as the text property.
|
as the text property.
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ class NWSpellEnchant:
|
|||||||
# Setters
|
# Setters
|
||||||
##
|
##
|
||||||
|
|
||||||
def setLanguage(self, language: str | None):
|
def setLanguage(self, language: str | None) -> None:
|
||||||
"""Load a dictionary for the language specified in the config.
|
"""Load a dictionary for the language specified in the config.
|
||||||
If that fails, we load a mock dictionary so that lookups don't
|
If that fails, we load a mock dictionary so that lookups don't
|
||||||
crash. Note that enchant will allow loading an empty string as
|
crash. Note that enchant will allow loading an empty string as
|
||||||
@@ -182,10 +182,10 @@ class FakeEnchant:
|
|||||||
def check(self, word: str) -> bool:
|
def check(self, word: str) -> bool:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def suggest(self, word) -> list[str]:
|
def suggest(self, word: str) -> list[str]:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def add_to_session(self, word: str):
|
def add_to_session(self, word: str) -> None:
|
||||||
return
|
return
|
||||||
|
|
||||||
# END Class FakeEnchant
|
# END Class FakeEnchant
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ ESCAPES = {r"\*": "*", r"\~": "~", r"\_": "_", r"\[": "[", r"\]": "]", r"\ ": ""
|
|||||||
RX_ESC = re.compile("|".join([re.escape(k) for k in ESCAPES.keys()]), flags=re.DOTALL)
|
RX_ESC = re.compile("|".join([re.escape(k) for k in ESCAPES.keys()]), flags=re.DOTALL)
|
||||||
|
|
||||||
|
|
||||||
def stripEscape(text) -> str:
|
def stripEscape(text: str) -> str:
|
||||||
"""Strip escaped Markdown characters from paragraph text."""
|
"""Strip escaped Markdown characters from paragraph text."""
|
||||||
if "\\" in text:
|
if "\\" in text:
|
||||||
return RX_ESC.sub(lambda x: ESCAPES[x.group(0)], text)
|
return RX_ESC.sub(lambda x: ESCAPES[x.group(0)], text)
|
||||||
|
|||||||
@@ -548,7 +548,7 @@ class ToOdt(Tokenizer):
|
|||||||
oVers = _mkTag("office", "version")
|
oVers = _mkTag("office", "version")
|
||||||
xSett = ET.Element(oRoot, attrib={oVers: X_VERS})
|
xSett = ET.Element(oRoot, attrib={oVers: X_VERS})
|
||||||
|
|
||||||
def putInZip(name, xObj, zipObj):
|
def putInZip(name: str, xObj: ET.Element, zipObj: ZipFile) -> None:
|
||||||
with zipObj.open(name, mode="w") as fObj:
|
with zipObj.open(name, mode="w") as fObj:
|
||||||
xml = ET.ElementTree(xObj)
|
xml = ET.ElementTree(xObj)
|
||||||
xml.write(fObj, encoding="utf-8", xml_declaration=True)
|
xml.write(fObj, encoding="utf-8", xml_declaration=True)
|
||||||
|
|||||||
@@ -795,7 +795,7 @@ class GuiPreferences(QDialog):
|
|||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def _selectTextFont(self):
|
def _selectTextFont(self) -> None:
|
||||||
"""Open the QFontDialog and set a font for the font style."""
|
"""Open the QFontDialog and set a font for the font style."""
|
||||||
current = QFont()
|
current = QFont()
|
||||||
current.setFamily(CONFIG.textFont)
|
current.setFamily(CONFIG.textFont)
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ def logException() -> None:
|
|||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
def formatException(exc) -> str:
|
def formatException(exc: BaseException) -> str:
|
||||||
"""Format an exception as a string the same way the default
|
"""Format an exception as a string the same way the default
|
||||||
exception handler does.
|
exception handler does.
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -381,7 +381,7 @@ class GuiDocEditor(QPlainTextEdit):
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def loadText(self, tHandle: str, tLine=None) -> bool:
|
def loadText(self, tHandle: str, tLine: int | None = None) -> bool:
|
||||||
"""Load text from a document into the editor. If we have an I/O
|
"""Load text from a document into the editor. If we have an I/O
|
||||||
error, we must handle this and clear the editor so that we don't
|
error, we must handle this and clear the editor so that we don't
|
||||||
risk overwriting the file if it exists. This can for instance
|
risk overwriting the file if it exists. This can for instance
|
||||||
@@ -1080,7 +1080,7 @@ class GuiDocEditor(QPlainTextEdit):
|
|||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def _cursorMoved(self):
|
def _cursorMoved(self) -> None:
|
||||||
"""Triggered when the cursor moved in the editor."""
|
"""Triggered when the cursor moved in the editor."""
|
||||||
self.docFooter.updateLineCount(self.textCursor())
|
self.docFooter.updateLineCount(self.textCursor())
|
||||||
return
|
return
|
||||||
@@ -2186,7 +2186,7 @@ class MetaCompleter(QMenu):
|
|||||||
# Internal Functions
|
# Internal Functions
|
||||||
##
|
##
|
||||||
|
|
||||||
def _emitComplete(self, pos: int, length: int, value: str):
|
def _emitComplete(self, pos: int, length: int, value: str) -> None:
|
||||||
"""Emit the signal to indicate a selection has been made."""
|
"""Emit the signal to indicate a selection has been made."""
|
||||||
self.complete.emit(pos, length, value)
|
self.complete.emit(pos, length, value)
|
||||||
return
|
return
|
||||||
@@ -2967,7 +2967,7 @@ class GuiDocEditHeader(QWidget):
|
|||||||
# Events
|
# Events
|
||||||
##
|
##
|
||||||
|
|
||||||
def mousePressEvent(self, event: QMouseEvent):
|
def mousePressEvent(self, event: QMouseEvent) -> None:
|
||||||
"""Capture a click on the title and ensure that the item is
|
"""Capture a click on the title and ensure that the item is
|
||||||
selected in the project tree.
|
selected in the project tree.
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -344,7 +344,7 @@ class GuiNovelToolBar(QWidget):
|
|||||||
# Internal Functions
|
# Internal Functions
|
||||||
##
|
##
|
||||||
|
|
||||||
def _addLastColAction(self, colType, actionLabel) -> None:
|
def _addLastColAction(self, colType: NovelTreeColumn, actionLabel: str) -> None:
|
||||||
"""Add a column selection entry to the last column menu."""
|
"""Add a column selection entry to the last column menu."""
|
||||||
aLast = self.mLastCol.addAction(actionLabel)
|
aLast = self.mLastCol.addAction(actionLabel)
|
||||||
aLast.setCheckable(True)
|
aLast.setCheckable(True)
|
||||||
|
|||||||
@@ -190,7 +190,7 @@ class GuiOutlineView(QWidget):
|
|||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot(str)
|
@pyqtSlot(str)
|
||||||
def _rootItemChanged(self, tHandle) -> None:
|
def _rootItemChanged(self, tHandle: str) -> None:
|
||||||
"""Handle root novel changed or needs to be refreshed."""
|
"""Handle root novel changed or needs to be refreshed."""
|
||||||
self.outlineTree.refreshTree(rootHandle=(tHandle or None), overRide=True)
|
self.outlineTree.refreshTree(rootHandle=(tHandle or None), overRide=True)
|
||||||
return
|
return
|
||||||
@@ -428,7 +428,7 @@ class GuiOutlineTree(QTreeWidget):
|
|||||||
##
|
##
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def hiddenColumns(self):
|
def hiddenColumns(self) -> dict[nwOutline, bool]:
|
||||||
return self._colHidden
|
return self._colHidden
|
||||||
|
|
||||||
##
|
##
|
||||||
@@ -586,7 +586,7 @@ class GuiOutlineTree(QTreeWidget):
|
|||||||
# Internal Functions
|
# Internal Functions
|
||||||
##
|
##
|
||||||
|
|
||||||
def _loadHeaderState(self):
|
def _loadHeaderState(self) -> None:
|
||||||
"""Load the state of the main tree header, that is, column order
|
"""Load the state of the main tree header, that is, column order
|
||||||
and column width.
|
and column width.
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -453,7 +453,7 @@ class GuiProjectToolBar(QWidget):
|
|||||||
|
|
||||||
def _buildRootMenu(self) -> None:
|
def _buildRootMenu(self) -> None:
|
||||||
"""Build the rood folder menu."""
|
"""Build the rood folder menu."""
|
||||||
def addClass(itemClass):
|
def addClass(itemClass: nwItemClass) -> None:
|
||||||
aNew = self.mAddRoot.addAction(trConst(nwLabels.CLASS_NAME[itemClass]))
|
aNew = self.mAddRoot.addAction(trConst(nwLabels.CLASS_NAME[itemClass]))
|
||||||
aNew.setIcon(SHARED.theme.getIcon(nwLabels.CLASS_ICON[itemClass]))
|
aNew.setIcon(SHARED.theme.getIcon(nwLabels.CLASS_ICON[itemClass]))
|
||||||
aNew.triggered.connect(lambda: self.projTree.newTreeItem(nwItemType.ROOT, itemClass))
|
aNew.triggered.connect(lambda: self.projTree.newTreeItem(nwItemType.ROOT, itemClass))
|
||||||
|
|||||||
@@ -944,7 +944,7 @@ class GuiMain(QMainWindow):
|
|||||||
# Events
|
# Events
|
||||||
##
|
##
|
||||||
|
|
||||||
def closeEvent(self, event: QCloseEvent):
|
def closeEvent(self, event: QCloseEvent) -> None:
|
||||||
"""Capture the closing event of the GUI and call the close
|
"""Capture the closing event of the GUI and call the close
|
||||||
function to handle all the close process steps.
|
function to handle all the close process steps.
|
||||||
"""
|
"""
|
||||||
@@ -1201,7 +1201,7 @@ class GuiMain(QMainWindow):
|
|||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def _toggleViewerPanelVisibility(self):
|
def _toggleViewerPanelVisibility(self) -> None:
|
||||||
"""Toggle the visibility of the document viewer panel."""
|
"""Toggle the visibility of the document viewer panel."""
|
||||||
CONFIG.showViewerPanel = not CONFIG.showViewerPanel
|
CONFIG.showViewerPanel = not CONFIG.showViewerPanel
|
||||||
self.docViewerPanel.setVisible(CONFIG.showViewerPanel)
|
self.docViewerPanel.setVisible(CONFIG.showViewerPanel)
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ class GuiDictionaries(QDialog):
|
|||||||
##
|
##
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def _doBrowseHunspell(self):
|
def _doBrowseHunspell(self) -> None:
|
||||||
"""Browse for a Free/Libre Office dictionary."""
|
"""Browse for a Free/Libre Office dictionary."""
|
||||||
ffilter = formatFileFilter([
|
ffilter = formatFileFilter([
|
||||||
(self.tr("Free or Libre Office extension"), "*.sox *.oxt"), "*"
|
(self.tr("Free or Libre Office extension"), "*.sox *.oxt"), "*"
|
||||||
@@ -193,7 +193,7 @@ class GuiDictionaries(QDialog):
|
|||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def _doImportHunspell(self):
|
def _doImportHunspell(self) -> None:
|
||||||
"""Import a hunspell dictionary from .sox or .oxt file."""
|
"""Import a hunspell dictionary from .sox or .oxt file."""
|
||||||
procErr = self.tr("Could not process dictionary file")
|
procErr = self.tr("Could not process dictionary file")
|
||||||
if self._installPath:
|
if self._installPath:
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ class GuiManuscriptBuild(QDialog):
|
|||||||
|
|
||||||
D_KEY = QtUserRole
|
D_KEY = QtUserRole
|
||||||
|
|
||||||
def __init__(self, parent: QWidget, build: BuildSettings):
|
def __init__(self, parent: QWidget, build: BuildSettings) -> None:
|
||||||
super().__init__(parent=parent)
|
super().__init__(parent=parent)
|
||||||
|
|
||||||
logger.debug("Create: GuiManuscriptBuild")
|
logger.debug("Create: GuiManuscriptBuild")
|
||||||
@@ -260,7 +260,7 @@ class GuiManuscriptBuild(QDialog):
|
|||||||
##
|
##
|
||||||
|
|
||||||
@pyqtSlot("QAbstractButton*")
|
@pyqtSlot("QAbstractButton*")
|
||||||
def _dialogButtonClicked(self, button: QAbstractButton):
|
def _dialogButtonClicked(self, button: QAbstractButton) -> None:
|
||||||
"""Handle button clicks from the dialog button box."""
|
"""Handle button clicks from the dialog button box."""
|
||||||
role = self.dlgButtons.buttonRole(button)
|
role = self.dlgButtons.buttonRole(button)
|
||||||
if role == QtRoleAction:
|
if role == QtRoleAction:
|
||||||
@@ -273,7 +273,7 @@ class GuiManuscriptBuild(QDialog):
|
|||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def _doSelectPath(self):
|
def _doSelectPath(self) -> None:
|
||||||
"""Select a folder for output."""
|
"""Select a folder for output."""
|
||||||
bPath = Path(self.buildPath.text())
|
bPath = Path(self.buildPath.text())
|
||||||
bPath = bPath if bPath.is_dir() else self._build.lastPath
|
bPath = bPath if bPath.is_dir() else self._build.lastPath
|
||||||
@@ -285,7 +285,7 @@ class GuiManuscriptBuild(QDialog):
|
|||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def _doResetBuildName(self):
|
def _doResetBuildName(self) -> None:
|
||||||
"""Generate a default build name."""
|
"""Generate a default build name."""
|
||||||
bName = f"{SHARED.project.data.name} - {self._build.name}"
|
bName = f"{SHARED.project.data.name} - {self._build.name}"
|
||||||
self.buildName.setText(bName)
|
self.buildName.setText(bName)
|
||||||
@@ -293,7 +293,7 @@ class GuiManuscriptBuild(QDialog):
|
|||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def _resetProgress(self):
|
def _resetProgress(self) -> None:
|
||||||
"""Set the progress bar back to 0."""
|
"""Set the progress bar back to 0."""
|
||||||
self.buildProgress.setValue(0)
|
self.buildProgress.setValue(0)
|
||||||
return
|
return
|
||||||
@@ -350,7 +350,7 @@ class GuiManuscriptBuild(QDialog):
|
|||||||
return items[0].data(self.D_KEY)
|
return items[0].data(self.D_KEY)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def _saveSettings(self):
|
def _saveSettings(self) -> None:
|
||||||
"""Save the user GUI settings."""
|
"""Save the user GUI settings."""
|
||||||
winWidth = CONFIG.rpxInt(self.width())
|
winWidth = CONFIG.rpxInt(self.width())
|
||||||
winHeight = CONFIG.rpxInt(self.height())
|
winHeight = CONFIG.rpxInt(self.height())
|
||||||
@@ -369,7 +369,7 @@ class GuiManuscriptBuild(QDialog):
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def _populateContentList(self):
|
def _populateContentList(self) -> None:
|
||||||
"""Build the content list."""
|
"""Build the content list."""
|
||||||
rootMap = {}
|
rootMap = {}
|
||||||
filtered = self._build.buildItemFilter(SHARED.project)
|
filtered = self._build.buildItemFilter(SHARED.project)
|
||||||
@@ -398,7 +398,7 @@ class GuiManuscriptBuild(QDialog):
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def _openOutputFolder(self):
|
def _openOutputFolder(self) -> None:
|
||||||
"""Open the build folder in the system's file explorer."""
|
"""Open the build folder in the system's file explorer."""
|
||||||
openExternalPath(Path(self.buildPath.text()))
|
openExternalPath(Path(self.buildPath.text()))
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -1312,7 +1312,7 @@ class _FormatTab(NScrollableForm):
|
|||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def _pageSizeValueChanged(self):
|
def _pageSizeValueChanged(self) -> None:
|
||||||
"""The user has changed the page size spin boxes, so we flip
|
"""The user has changed the page size spin boxes, so we flip
|
||||||
the page size box to Custom.
|
the page size box to Custom.
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -753,7 +753,7 @@ class _NewProjectForm(QWidget):
|
|||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def _syncSwitches(self):
|
def _syncSwitches(self) -> None:
|
||||||
"""Check if the add notes option should also be switched off."""
|
"""Check if the add notes option should also be switched off."""
|
||||||
addPlot = self.addPlot.isChecked()
|
addPlot = self.addPlot.isChecked()
|
||||||
addChar = self.addChar.isChecked()
|
addChar = self.addChar.isChecked()
|
||||||
|
|||||||
+13
-7
@@ -47,7 +47,7 @@ def extractVersion(beQuiet: bool = False) -> tuple[str, str, str]:
|
|||||||
"""Extract the novelWriter version number without having to import
|
"""Extract the novelWriter version number without having to import
|
||||||
anything else from the main package.
|
anything else from the main package.
|
||||||
"""
|
"""
|
||||||
def getValue(text):
|
def getValue(text: str) -> str:
|
||||||
bits = text.partition("=")
|
bits = text.partition("=")
|
||||||
return bits[2].strip().strip('"')
|
return bits[2].strip().strip('"')
|
||||||
|
|
||||||
@@ -176,7 +176,7 @@ def cleanBuildDirs() -> None:
|
|||||||
print("Cleaning up build environment ...")
|
print("Cleaning up build environment ...")
|
||||||
print("")
|
print("")
|
||||||
|
|
||||||
def removeFolder(rmDir):
|
def removeFolder(rmDir: str) -> None:
|
||||||
if os.path.isdir(rmDir):
|
if os.path.isdir(rmDir):
|
||||||
try:
|
try:
|
||||||
shutil.rmtree(rmDir)
|
shutil.rmtree(rmDir)
|
||||||
@@ -320,7 +320,7 @@ def buildQtI18nTS(sysArgs: list[str]) -> None:
|
|||||||
print("=============================")
|
print("=============================")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from PyQt6.lupdate import lupdate
|
from PyQt6.lupdate.lupdate import lupdate
|
||||||
except ImportError:
|
except ImportError:
|
||||||
print("ERROR: This command requires lupdate from PyQt6")
|
print("ERROR: This command requires lupdate from PyQt6")
|
||||||
print("On Debian/Ubuntu, install: pyqt6-dev-tools")
|
print("On Debian/Ubuntu, install: pyqt6-dev-tools")
|
||||||
@@ -911,7 +911,7 @@ def makeAppImage(sysArgs: list[str]) -> list[str]:
|
|||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import python_appimage # noqa F401
|
import python_appimage # noqa: F401 # type: ignore
|
||||||
except ImportError:
|
except ImportError:
|
||||||
print(
|
print(
|
||||||
"ERROR: Package 'python-appimage' is missing on this system.\n"
|
"ERROR: Package 'python-appimage' is missing on this system.\n"
|
||||||
@@ -1252,12 +1252,12 @@ def makeWindowsEmbedded(sysArgs: list[str]) -> None:
|
|||||||
# Clean Up Files
|
# Clean Up Files
|
||||||
# ==============
|
# ==============
|
||||||
|
|
||||||
def unlinkIfFound(delFile):
|
def unlinkIfFound(delFile: str) -> None:
|
||||||
if os.path.isfile(delFile):
|
if os.path.isfile(delFile):
|
||||||
os.unlink(delFile)
|
os.unlink(delFile)
|
||||||
print("Deleted: %s" % delFile)
|
print("Deleted: %s" % delFile)
|
||||||
|
|
||||||
def deleteFolder(delPath):
|
def deleteFolder(delPath: str) -> None:
|
||||||
if os.path.isdir(delPath):
|
if os.path.isdir(delPath):
|
||||||
shutil.rmtree(delPath)
|
shutil.rmtree(delPath)
|
||||||
print("Deleted: %s" % delPath)
|
print("Deleted: %s" % delPath)
|
||||||
@@ -1561,6 +1561,9 @@ def xdgUninstall() -> None:
|
|||||||
|
|
||||||
def winInstall() -> None:
|
def winInstall() -> None:
|
||||||
"""Will attempt to install icons and make a launcher for Windows."""
|
"""Will attempt to install icons and make a launcher for Windows."""
|
||||||
|
if sys.platform != "win32":
|
||||||
|
raise Exception("This method only runs on Windows")
|
||||||
|
|
||||||
import winreg
|
import winreg
|
||||||
try:
|
try:
|
||||||
import win32com.client
|
import win32com.client
|
||||||
@@ -1654,7 +1657,7 @@ def winInstall() -> None:
|
|||||||
print("")
|
print("")
|
||||||
print("Creating registry keys ...")
|
print("Creating registry keys ...")
|
||||||
|
|
||||||
def setKey(kPath, kName, kVal):
|
def setKey(kPath: str, kName: str, kVal: str) -> None:
|
||||||
winreg.CreateKey(winreg.HKEY_CURRENT_USER, kPath)
|
winreg.CreateKey(winreg.HKEY_CURRENT_USER, kPath)
|
||||||
regKey = winreg.OpenKey(winreg.HKEY_CURRENT_USER, kPath, 0, winreg.KEY_WRITE)
|
regKey = winreg.OpenKey(winreg.HKEY_CURRENT_USER, kPath, 0, winreg.KEY_WRITE)
|
||||||
winreg.SetValueEx(regKey, kName, 0, winreg.REG_SZ, kVal)
|
winreg.SetValueEx(regKey, kName, 0, winreg.REG_SZ, kVal)
|
||||||
@@ -1688,6 +1691,9 @@ def winInstall() -> None:
|
|||||||
|
|
||||||
def winUninstall() -> None:
|
def winUninstall() -> None:
|
||||||
"""Will attempt to uninstall icons previously installed."""
|
"""Will attempt to uninstall icons previously installed."""
|
||||||
|
if sys.platform != "win32":
|
||||||
|
raise Exception("This method only runs on Windows")
|
||||||
|
|
||||||
import winreg
|
import winreg
|
||||||
try:
|
try:
|
||||||
import win32com.client
|
import win32com.client
|
||||||
|
|||||||
@@ -1,2 +1,3 @@
|
|||||||
flake8
|
flake8
|
||||||
flake8-pep585
|
flake8-pep585
|
||||||
|
flake8-annotations
|
||||||
|
|||||||
Reference in New Issue
Block a user