diff --git a/.github/scripts/checkTranslation.py b/.github/scripts/checkTranslation.py index 9d03dc6..df12632 100644 --- a/.github/scripts/checkTranslation.py +++ b/.github/scripts/checkTranslation.py @@ -2,8 +2,9 @@ # This file is covered by the GNU General Public License. # See the file COPYING for more details. -import sys import os +import sys + from crowdin_api import CrowdinClient diff --git a/.github/workflows/manual-release.yaml b/.github/workflows/manual-release.yaml index 7ec95ba..4a3b60c 100644 --- a/.github/workflows/manual-release.yaml +++ b/.github/workflows/manual-release.yaml @@ -44,7 +44,7 @@ jobs: $curDate = Get-Date -Format "yyyyMMdd" $curYear = Get-Date -Format "yyyy" $tagName = "v" + (Get-Date -Format "yy.MM.dd") - + echo "CUR_DATE=$curDate" >> $env:GITHUB_ENV echo "CUR_YEAR=$curYear" >> $env:GITHUB_ENV echo "TAG_NAME=$tagName" >> $env:GITHUB_ENV diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 207177d..fdf46c6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -26,7 +26,7 @@ repos: - id: check-hooks-apply - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v5.0.0 + rev: v6.0.0 hooks: # Prevents commits to certain branches - id: no-commit-to-branch @@ -60,7 +60,7 @@ repos: # Avoids using reserved Windows filenames. - id: check-illegal-windows-names - repo: https://github.com/asottile/add-trailing-comma - rev: v3.2.0 + rev: v4.0.0 hooks: # Ruff preserves indent/new-line formatting of function arguments, list items, and similar iterables, # if a trailing comma is added. @@ -69,7 +69,7 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit # Matches Ruff version in pyproject. - rev: v0.12.7 + rev: v0.16.6 hooks: - id: ruff name: lint with ruff diff --git a/addon/appModules/mp3directcut.py b/addon/appModules/mp3directcut.py index 1edda9a..14d6348 100644 --- a/addon/appModules/mp3directcut.py +++ b/addon/appModules/mp3directcut.py @@ -7,36 +7,38 @@ # See the file COPYING for more details. from __future__ import unicode_literals # To ensure unicode compatibility with both python 2 and 3. -import appModuleHandler + import re -import windowUtils -from typing import Callable +from collections.abc import Callable + +import appModuleHandler import controlTypes +import windowUtils if hasattr(controlTypes, "ROLE_PANE"): - from controlTypes import ROLE_PANE, ROLE_EDITABLETEXT + from controlTypes import ROLE_EDITABLETEXT, ROLE_PANE else: ROLE_PANE = controlTypes.Role.PANE ROLE_EDITABLETEXT = controlTypes.Role.EDITABLETEXT -from datetime import datetime -from keyboardHandler import KeyboardInputGesture as kig import os -import buildVersion +import sys +from datetime import datetime + +import addonHandler import api +import buildVersion +from keyboardHandler import KeyboardInputGesture as kig +from NVDAObjects.IAccessible import IAccessible, getNVDAObjectFromEvent from scriptHandler import getLastScriptRepeatCount, script +from ui import message from winUser import ( CHILDID_SELF, - OBJID_CLIENT, - setFocus, - mouse_event, MOUSEEVENTF_LEFTDOWN, MOUSEEVENTF_LEFTUP, + OBJID_CLIENT, + mouse_event, + setFocus, ) -from ui import message -import sys -from NVDAObjects.IAccessible import IAccessible, getNVDAObjectFromEvent - -import addonHandler addonHandler.initTranslation() _: Callable[[str], str] @@ -107,12 +109,12 @@ ) -def timeSplitter(time): # noqa: C901 +def timeSplitter(time): hours = minutes = seconds = hundredths = thousandths = "" if ":" in time: hrs = time.split(":") if hrs[0] != "00" and hrs[0] != "0": - hours = "{0} {1}, ".format(hrs[0], hr) + hours = f"{hrs[0]} {hr}, " if hrs[1].split("'")[0] != "00": minutes = hrs[1].split("'")[0] else: @@ -123,7 +125,7 @@ def timeSplitter(time): # noqa: C901 if len(minutes) > 1: if minutes[0] == "0": minutes = minutes[1] - minutes = "{0} {1}, ".format(minutes, min) + minutes = f"{minutes} {min}, " try: scnds = time.split("'")[1].split(".")[0] except IndexError: @@ -134,13 +136,13 @@ def timeSplitter(time): # noqa: C901 if len(seconds) > 1: if seconds[0] == "0": seconds = seconds[1] - seconds = "{0} {1}, ".format(seconds, sec) + seconds = f"{seconds} {sec}, " hd = time.split(".")[1].split()[0] if hd != "00" and hd != "000": if len(hd) == 3: - thousandths = "{0} {1}.".format(hd, th) + thousandths = f"{hd} {th}." else: - hundredths = "{0} {1}.".format(hd, hun) + hundredths = f"{hd} {hun}." timeSplitter = ( hours + minutes + seconds + hundredths if not thousandths else hours + minutes + seconds + thousandths ) @@ -253,7 +255,7 @@ def part(flag=None): text = text.split(")") text = text[0] text = text.replace("/", " {0} ".format(_("of"))) - return "{0} {1}".format(announce[10], text) if not flag else "{0} {1}".format(_("Part"), text) + return f"{announce[10]} {text}" if not flag else "{0} {1}".format(_("Part"), text) def selectionDuration(): @@ -339,9 +341,9 @@ def timeRemaining(): hORm = len(total.split(".")[1]) fmt = "%H:%M'%S.%f" if ":" not in actual: - actual = "0:{0}".format(actual) + actual = f"0:{actual}" if ":" not in total: - total = "0:{0}".format(total) + total = f"0:{total}" result = datetime.strptime(total, fmt) - datetime.strptime(actual, fmt) result = str(result).decode("utf-8") if sys.version_info.major == 2 else str(result) result = result.replace(":", "'") @@ -510,15 +512,15 @@ def script_up(self, gesture): if not actual: actual = announce[1] if actual == totalTime(): - actual = "{0} {1}".format(actual, announce[2]) + actual = f"{actual} {announce[2]}" sayMessage(announce[5] + " : " + actual + " " + actualDurationPercentage()) else: actual = actualDuration() if not actual: - sayMessage("{0}, {1}".format(announce[0], announce[1])) + sayMessage(f"{announce[0]}, {announce[1]}") return if actual == totalTime(): - actual = "{0} {1}".format(actual, announce[2]) + actual = f"{actual} {announce[2]}" # Translators: Message to indicate the elapsed time. sayMessage( "{0}, {1} {2} {3}".format( @@ -550,15 +552,15 @@ def script_down(self, gesture): if not actual: actual = announce[1] if actual == totalTime(): - actual = "{0} {1}".format(actual, announce[2]) + actual = f"{actual} {announce[2]}" sayMessage(announce[6] + " : " + actual + " " + actualDurationPercentage()) else: actual = actualDuration() if not actual: - sayMessage("{0}, {1}".format(announce[0], announce[1])) + sayMessage(f"{announce[0]}, {announce[1]}") return if actual == totalTime(): - actual = "{0} {1}".format(actual, announce[2]) + actual = f"{actual} {announce[2]}" # Translators: Message to indicate the elapsed time. sayMessage( "{0}, {1} {2} {3}".format( @@ -603,7 +605,7 @@ def script_elapsedTime(self, gesture): if repeat == 0: message(text) elif repeat == 1: - message("{0} {1}".format(announce[8], totalTime())) + message(f"{announce[8]} {totalTime()}") @script( gesture="kb:control+shift+r", @@ -771,7 +773,9 @@ def event_valueChange(self, obj, nextHandler): def event_NVDAObject_init(self, obj): isCustomLabel = next((x for x in addonHandler.getRunningAddons() if x.name == "CustomLabels"), None) - isColumnsReview = next((x for x in addonHandler.getRunningAddons() if x.name == "columnsReview"), None) + isColumnsReview = next( + (x for x in addonHandler.getRunningAddons() if x.name == "columnsReview"), None + ) if not isCustomLabel and not isColumnsReview: if obj and obj.firstChild and obj.firstChild.windowControlID == 641: obj.name = obj.firstChild.name diff --git a/addon/globalPlugins/mp3DirectCut/__init__.py b/addon/globalPlugins/mp3DirectCut/__init__.py index 2941a46..3679cc7 100644 --- a/addon/globalPlugins/mp3DirectCut/__init__.py +++ b/addon/globalPlugins/mp3DirectCut/__init__.py @@ -6,16 +6,18 @@ # This file is covered by the GNU General Public License. # See the file COPYING for more details. -import globalPluginHandler -import globalVars -from scriptHandler import script +from collections.abc import Callable + import addonHandler import buildVersion -from .mp3DirectCutDialog import Mp3DirectCutDialog, Mp3DirectCutPanel -from typing import Callable +import config +import globalPluginHandler +import globalVars import gui import wx -import config +from scriptHandler import script + +from .mp3DirectCutDialog import Mp3DirectCutDialog, Mp3DirectCutPanel addonHandler.initTranslation() _: Callable[[str], str] @@ -37,7 +39,7 @@ class GlobalPlugin(globalPluginHandler.GlobalPlugin): scriptCategory = ADDON_SUMMARY def __init__(self, *args, **kwargs): - super(GlobalPlugin, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) if globalVars.appArgs.secure or (hasattr(config, "isAppX") and config.isAppX): return # This block ensures compatibility with NVDA versions prior to 2018.2 which includes the settings panel. @@ -59,7 +61,7 @@ def createSubMenu(self): gui.mainFrame.sysTrayIcon.Bind(wx.EVT_MENU, self.onMp3DirectCutDialog, self.mp3DirectCut) def terminate(self): - super(GlobalPlugin, self).terminate() + super().terminate() if hasattr(gui, "NVDASettingsDialog"): gui.NVDASettingsDialog.categoryClasses.remove(Mp3DirectCutPanel) if hasattr(self, "preferencesMenu"): diff --git a/addon/globalPlugins/mp3DirectCut/mp3DirectCutDialog.py b/addon/globalPlugins/mp3DirectCut/mp3DirectCutDialog.py index 98fb80a..6d74aab 100644 --- a/addon/globalPlugins/mp3DirectCut/mp3DirectCutDialog.py +++ b/addon/globalPlugins/mp3DirectCut/mp3DirectCutDialog.py @@ -6,11 +6,12 @@ # This file is covered by the GNU General Public License. # See the file COPYING for more details. +from collections.abc import Callable + import addonHandler import config import wx from gui import guiHelper -from typing import Callable # This block ensures compatibility with NVDA versions prior to 2018.2 which includes the settings panel. try: @@ -83,4 +84,4 @@ def onOk(self, evt): config.conf["mp3DCReport"]["space"] = self.reportSpaceCheckBox.GetValue() config.conf["mp3DCReport"]["marker"] = self.reportMarkerCheckBox.GetValue() config.conf["mp3DCReport"]["other"] = self.reportOtherCheckBox.GetValue() - super(Mp3DirectCutDialog, self).onOk(evt) + super().onOk(evt) diff --git a/addon/installTasks.py b/addon/installTasks.py index 7963bc1..db794ae 100644 --- a/addon/installTasks.py +++ b/addon/installTasks.py @@ -6,9 +6,10 @@ # This file is covered by the GNU General Public License. # See the file COPYING for more details. +from collections.abc import Callable + import addonHandler import gui -from typing import Callable import wx addonHandler.initTranslation() diff --git a/changelog.md b/changelog.md index 37625f2..71f4691 100644 --- a/changelog.md +++ b/changelog.md @@ -1,4 +1,3 @@ ## Changes for 20260803.0.0 * Ensure compatibility with columnsReview and CustomLabels. - diff --git a/site_scons/site_tools/NVDATool/__init__.py b/site_scons/site_tools/NVDATool/__init__.py index a71857d..1bee61e 100644 --- a/site_scons/site_tools/NVDATool/__init__.py +++ b/site_scons/site_tools/NVDATool/__init__.py @@ -23,23 +23,25 @@ """ -from SCons.Script import Environment, Builder +from SCons.Script import Builder, Environment from .addon import createAddonBundleFromPath -from .manifests import generateManifest, generateTranslatedManifest from .docs import md2html +from .manifests import generateManifest, generateTranslatedManifest def generate(env: Environment): env.SetDefault(excludePatterns=tuple()) addonAction = env.Action( - lambda target, source, env: createAddonBundleFromPath( - source[0].abspath, - target[0].abspath, - env["excludePatterns"], - ) - and None, + lambda target, source, env: ( + createAddonBundleFromPath( + source[0].abspath, + target[0].abspath, + env["excludePatterns"], + ) + and None + ), lambda target, source, env: f"Generating Addon {target[0]}", ) env["BUILDERS"]["NVDAAddon"] = Builder( @@ -53,15 +55,17 @@ def generate(env: Environment): env.SetDefault(speechDictionaries={}) manifestAction = env.Action( - lambda target, source, env: generateManifest( - source[0].abspath, - target[0].abspath, - addon_info=env["addon_info"], - brailleTables=env["brailleTables"], - symbolDictionaries=env["symbolDictionaries"], - speechDictionaries=env["speechDictionaries"], - ) - and None, + lambda target, source, env: ( + generateManifest( + source[0].abspath, + target[0].abspath, + addon_info=env["addon_info"], + brailleTables=env["brailleTables"], + symbolDictionaries=env["symbolDictionaries"], + speechDictionaries=env["speechDictionaries"], + ) + and None + ), lambda target, source, env: f"Generating manifest {target[0]}", ) env["BUILDERS"]["NVDAManifest"] = Builder( @@ -71,16 +75,18 @@ def generate(env: Environment): ) translatedManifestAction = env.Action( - lambda target, source, env: generateTranslatedManifest( - source[1].abspath, - target[0].abspath, - mo=source[0].abspath, - addon_info=env["addon_info"], - brailleTables=env["brailleTables"], - symbolDictionaries=env["symbolDictionaries"], - speechDictionaries=env["speechDictionaries"], - ) - and None, + lambda target, source, env: ( + generateTranslatedManifest( + source[1].abspath, + target[0].abspath, + mo=source[0].abspath, + addon_info=env["addon_info"], + brailleTables=env["brailleTables"], + symbolDictionaries=env["symbolDictionaries"], + speechDictionaries=env["speechDictionaries"], + ) + and None + ), lambda target, source, env: f"Generating translated manifest {target[0]}", ) @@ -93,14 +99,16 @@ def generate(env: Environment): env.SetDefault(mdExtensions={}) mdAction = env.Action( - lambda target, source, env: md2html( - source[0].path, - target[0].path, - moFile=env["moFile"].path if env["moFile"] else None, - mdExtensions=env["mdExtensions"], - addon_info=env["addon_info"], - ) - and None, + lambda target, source, env: ( + md2html( + source[0].path, + target[0].path, + moFile=env["moFile"].path if env["moFile"] else None, + mdExtensions=env["mdExtensions"], + addon_info=env["addon_info"], + ) + and None + ), lambda target, source, env: f"Generating {target[0]}", ) env["BUILDERS"]["md2html"] = env.Builder( diff --git a/site_scons/site_tools/NVDATool/addon.py b/site_scons/site_tools/NVDATool/addon.py index 7d67516..ee1fc5a 100644 --- a/site_scons/site_tools/NVDATool/addon.py +++ b/site_scons/site_tools/NVDATool/addon.py @@ -5,7 +5,7 @@ def matchesNoPatterns(path: Path, patterns: Iterable[str]) -> bool: """Checks if the path, the first argument, does not match any of the patterns passed as the second argument.""" - return not any((path.match(pattern) for pattern in patterns)) + return not any(path.match(pattern) for pattern in patterns) def createAddonBundleFromPath(path: str | Path, dest: str, excludePatterns: Iterable[str]): diff --git a/site_scons/site_tools/NVDATool/manifests.py b/site_scons/site_tools/NVDATool/manifests.py index 7723b0b..edd97b2 100644 --- a/site_scons/site_tools/NVDATool/manifests.py +++ b/site_scons/site_tools/NVDATool/manifests.py @@ -2,7 +2,7 @@ import gettext from functools import partial -from .typings import AddonInfo, BrailleTables, SymbolDictionaries, SpeechDictionaries +from .typings import AddonInfo, BrailleTables, SpeechDictionaries, SymbolDictionaries from .utils import format_nested_section diff --git a/site_scons/site_tools/NVDATool/typings.py b/site_scons/site_tools/NVDATool/typings.py index 0375538..009c2f3 100644 --- a/site_scons/site_tools/NVDATool/typings.py +++ b/site_scons/site_tools/NVDATool/typings.py @@ -1,4 +1,4 @@ -from typing import TypedDict, Protocol +from typing import Protocol, TypedDict class AddonInfo(TypedDict):