From 75d1f35aab37e28251318021377aa7f8bbcd61d2 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 5 Oct 2026 19:35:30 +0000 Subject: [PATCH 1/2] [pre-commit.ci] Pre-commit autoupdate. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.15.20 → v0.16.10](https://github.com/astral-sh/ruff-pre-commit/compare/v0.15.20...v0.16.10) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f7719aa3..ad8ad5b1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,7 +11,7 @@ repos: args: [--fix=lf] - id: check-case-conflict - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.15.20 # must match pyproject.toml + rev: v0.16.10 # must match pyproject.toml hooks: - id: ruff args: [--extend-select, I, --fix] From c4718043b3820e02b3196b9d6c2acdf19f9ca0c3 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 5 Oct 2026 19:41:19 +0000 Subject: [PATCH 2/2] [pre-commit.ci] Auto fixes from pre-commit.com hooks. --- README.md | 2 -- __init__.py | 8 ++++---- basic_features/__init__.py | 4 ++-- basic_features/basic_mod_data_checker.py | 7 ++++--- basic_features/basic_save_game_info.py | 6 ++---- basic_game.py | 11 ++++++----- basic_game_ini.py | 2 -- eadesktop_utils.py | 9 +++------ epic_utils.py | 3 +-- games/baldursgate3/bg3_file_mapper.py | 4 ++-- games/baldursgate3/bg3_utils.py | 3 +-- games/baldursgate3/lslib_retriever.py | 4 ++-- games/baldursgate3/pak_parser.py | 5 ++--- games/game_arkhamcity.py | 3 +-- games/game_baldursgate3.py | 2 +- games/game_blackandwhite2.py | 2 -- games/game_borderlands1.py | 4 ++-- games/game_cyberpunk2077.py | 6 +++--- games/game_divinityoriginalsinee.py | 2 -- games/game_finalfantasy7rebirth.py | 4 ++-- games/game_finalfantasy7remake.py | 6 +++--- games/game_masterduel.py | 7 +++---- games/game_nfshs.py | 2 -- games/game_oblivion_remaster.py | 5 +++-- games/game_silenthill2remake.py | 4 +--- games/game_sims4.py | 8 ++++---- games/game_tdu.py | 2 -- games/game_tdu2.py | 2 -- games/game_thps3.py | 2 -- games/game_thps4.py | 2 -- games/game_thug.py | 2 -- games/game_thug2.py | 2 -- games/game_tmuf.py | 2 -- games/game_valheim.py | 17 ++++++----------- games/game_vampirebloodlines.py | 3 +-- games/game_witcher1.py | 6 +++--- games/game_witcher2.py | 3 +-- games/game_witcher3.py | 3 +-- games/game_zeusandposeidon.py | 8 +++----- games/oblivion_remaster/game_plugins.py | 2 +- games/oblivion_remaster/mod_data_checker.py | 4 +--- games/oblivion_remaster/paks/view.py | 2 +- games/oblivion_remaster/paks/widget.py | 4 ++-- games/oblivion_remaster/ue4ss/model.py | 3 ++- games/oblivion_remaster/ue4ss/view.py | 2 +- games/stalkeranomaly/XRIO.py | 8 +++----- games/stalkeranomaly/XRObject.py | 5 +---- games/stalkeranomaly/XRSave.py | 5 ++--- origin_utils.py | 4 +--- steam_utils.py | 8 ++++---- 50 files changed, 86 insertions(+), 138 deletions(-) diff --git a/README.md b/README.md index 6fbed59b..0f2993dc 100644 --- a/README.md +++ b/README.md @@ -100,7 +100,6 @@ from ..basic_game import BasicGame class Witcher3Game(BasicGame): - Name = "Witcher 3 Support Plugin" Author = "Holt59" Version = "1.0.0a" @@ -129,7 +128,6 @@ import mobase class Witcher3Game(BasicGame): - Name = "Witcher 3 Support Plugin" Author = "Holt59" diff --git a/__init__.py b/__init__.py index f04289be..48e5c74a 100644 --- a/__init__.py +++ b/__init__.py @@ -23,7 +23,7 @@ def createPlugins(): # List of game class from python: - game_plugins: typing.List[IPlugin] = [] + game_plugins: list[IPlugin] = [] # We are going to list all game plugins: curpath = os.path.abspath(os.path.dirname(__file__)) @@ -43,9 +43,9 @@ def createPlugins(): try: module = importlib.import_module(".games." + module_p[:-3], __package__) except ImportError as e: - print("Failed to import module {}: {}".format(module_p, e), file=sys.stderr) + print(f"Failed to import module {module_p}: {e}", file=sys.stderr) except Exception as e: - print("Failed to import module {}: {}".format(module_p, e), file=sys.stderr) + print(f"Failed to import module {module_p}: {e}", file=sys.stderr) # Lookup game plugins: for name in dir(module): @@ -60,7 +60,7 @@ def createPlugins(): game_plugins.append(obj()) except Exception as e: print( - "Failed to instantiate {}: {}".format(name, e), + f"Failed to instantiate {name}: {e}", file=sys.stderr, ) for path in pathlib.Path(escaped_games_path).rglob("plugins/__init__.py"): diff --git a/basic_features/__init__.py b/basic_features/__init__.py index 9326dd9c..005078f9 100644 --- a/basic_features/__init__.py +++ b/basic_features/__init__.py @@ -3,8 +3,8 @@ from .basic_save_game_info import BasicGameSaveGameInfo __all__ = [ - "BasicModDataChecker", "BasicGameSaveGameInfo", - "GlobPatterns", "BasicLocalSavegames", + "BasicModDataChecker", + "GlobPatterns", ] diff --git a/basic_features/basic_mod_data_checker.py b/basic_features/basic_mod_data_checker.py index 1d061eb9..5346aeb8 100644 --- a/basic_features/basic_mod_data_checker.py +++ b/basic_features/basic_mod_data_checker.py @@ -2,8 +2,9 @@ import fnmatch import re +from collections.abc import Iterable from dataclasses import dataclass, field -from typing import Iterable, Literal +from typing import Literal import mobase @@ -28,7 +29,7 @@ def regex_from_glob_list(glob_list: Iterable[str]) -> re.Pattern[str]: give the `glob_list` index. """ return re.compile( - "|".join(f"({fnmatch.translate(f)})" for f in glob_list), re.I + "|".join(f"({fnmatch.translate(f)})" for f in glob_list), re.IGNORECASE ) def match(self, value: str) -> bool: @@ -48,7 +49,7 @@ def __init__(self, globs: GlobPatterns) -> None: self.valid = OptionalRegexPattern(globs.valid) self.move = { - key: re.compile(fnmatch.translate(key), re.I) for key in globs.move + key: re.compile(fnmatch.translate(key), re.IGNORECASE) for key in globs.move } self.ignore = OptionalRegexPattern(globs.ignore) diff --git a/basic_features/basic_save_game_info.py b/basic_features/basic_save_game_info.py index 436e724d..5377fab2 100644 --- a/basic_features/basic_save_game_info.py +++ b/basic_features/basic_save_game_info.py @@ -1,10 +1,8 @@ -# -*- encoding: utf-8 -*- - import sys -from collections.abc import Mapping +from collections.abc import Callable, Mapping, Sequence from datetime import datetime from pathlib import Path -from typing import Any, Callable, Self, Sequence +from typing import Any, Self from PyQt6.QtCore import QDateTime, QLocale, Qt from PyQt6.QtGui import QImage, QPixmap diff --git a/basic_game.py b/basic_game.py index e0f7ba54..040782bd 100644 --- a/basic_game.py +++ b/basic_game.py @@ -2,8 +2,9 @@ import shutil import sys +from collections.abc import Callable from pathlib import Path -from typing import Callable, Generic, TypeVar +from typing import Generic, TypeVar from PyQt6.QtCore import QDir, QFileInfo, QStandardPaths from PyQt6.QtGui import QIcon @@ -49,7 +50,7 @@ def replace_variables(value: str, game: BasicGame) -> str: class BasicGameMapping(Generic[_T]): # The game: - _game: "BasicGame" + _game: BasicGame # Name of the attribute for exposure: _exposed_name: str @@ -61,7 +62,7 @@ class BasicGameMapping(Generic[_T]): _required: bool # Callable returning a default value (if not required): - _default: Callable[["BasicGame"], _T] + _default: Callable[[BasicGame], _T] # Function to apply to the value: _apply_fn: Callable[[_T | str], _T] | None @@ -256,7 +257,7 @@ def __init__(self, game: BasicGame): game, "Description", "description", - lambda g: "Adds basic support for game {}.".format(g.gameName()), + lambda g: f"Adds basic support for game {g.gameName()}.", ) self.gameName = BasicGameMapping(game, "GameName", "gameName") self.gameShortName = BasicGameMapping(game, "GameShortName", "gameShortName") @@ -416,7 +417,7 @@ def setup(): _gamePath: str def __init__(self): - super(BasicGame, self).__init__() + super().__init__() if not hasattr(self, "_fromName"): self._fromName = self.__class__.__name__ diff --git a/basic_game_ini.py b/basic_game_ini.py index c9e0af6d..3c072866 100644 --- a/basic_game_ini.py +++ b/basic_game_ini.py @@ -1,5 +1,3 @@ -# -*- encoding: utf-8 -*- - import configparser import os diff --git a/eadesktop_utils.py b/eadesktop_utils.py index 5720556e..0a1f4658 100644 --- a/eadesktop_utils.py +++ b/eadesktop_utils.py @@ -1,15 +1,12 @@ -# -*- encoding: utf-8 -*- - import configparser import os import sys import xml.etree.ElementTree as et from configparser import NoOptionError from pathlib import Path -from typing import Dict -def find_games(errors: list[tuple[str, Exception]] | None = None) -> Dict[str, Path]: +def find_games(errors: list[tuple[str, Exception]] | None = None) -> dict[str, Path]: """ Find the list of EA Desktop games installed. @@ -17,7 +14,7 @@ def find_games(errors: list[tuple[str, Exception]] | None = None) -> Dict[str, P A mapping from EA Desktop content IDs to install locations for available EA Desktop games. """ - games: Dict[str, Path] = {} + games: dict[str, Path] = {} local_app_data_path = os.path.expandvars("%LocalAppData%") ea_desktop_settings_path = Path(local_app_data_path).joinpath( @@ -82,4 +79,4 @@ def find_games(errors: list[tuple[str, Exception]] | None = None) -> Dict[str, P if __name__ == "__main__": games = find_games() for k, v in games.items(): - print("Found game with id {} at {}.".format(k, v)) + print(f"Found game with id {k} at {v}.") diff --git a/epic_utils.py b/epic_utils.py index b7d34963..dedd693c 100644 --- a/epic_utils.py +++ b/epic_utils.py @@ -1,4 +1,3 @@ -# -*- encoding: utf-8 -*- from __future__ import annotations import itertools @@ -98,4 +97,4 @@ def find_games(errors: ErrorList | None = None) -> dict[str, Path]: if __name__ == "__main__": games = find_games() for k, v in games.items(): - print("Found game with id {} at {}.".format(k, v)) + print(f"Found game with id {k} at {v}.") diff --git a/games/baldursgate3/bg3_file_mapper.py b/games/baldursgate3/bg3_file_mapper.py index 0ae6ef8b..c27f7c65 100644 --- a/games/baldursgate3/bg3_file_mapper.py +++ b/games/baldursgate3/bg3_file_mapper.py @@ -1,7 +1,7 @@ import functools import os +from collections.abc import Callable from pathlib import Path -from typing import Callable, Optional from PyQt6.QtCore import QDir, QLoggingCategory, qDebug, qInfo, qWarning from PyQt6.QtWidgets import QApplication @@ -75,7 +75,7 @@ def mappings(self) -> list[mobase.Mapping]: def map_files( self, path: Path, - dest: Optional[Path] = None, + dest: Path | None = None, pattern: str = "*", rel: bool = True, only_convert: bool = False, diff --git a/games/baldursgate3/bg3_utils.py b/games/baldursgate3/bg3_utils.py index 79c8a7ce..b41f317b 100644 --- a/games/baldursgate3/bg3_utils.py +++ b/games/baldursgate3/bg3_utils.py @@ -1,6 +1,5 @@ import functools import shutil -import typing from pathlib import Path from time import sleep @@ -193,7 +192,7 @@ def on_settings_changed( def construct_modsettings_xml( self, exec_path: str = "", - working_dir: typing.Optional[QDir] = None, + working_dir: QDir | None = None, args: str = "", force_reparse_metadata: bool = False, ) -> bool: diff --git a/games/baldursgate3/lslib_retriever.py b/games/baldursgate3/lslib_retriever.py index 4c3d797c..9a77b9cc 100644 --- a/games/baldursgate3/lslib_retriever.py +++ b/games/baldursgate3/lslib_retriever.py @@ -19,13 +19,13 @@ def __init__(self, utils: bg3_utils.BG3Utils): def _needed_lslib_files(self): return { self._utils.tools_dir / x - for x in { + for x in ( "CommandLineArgumentsParser.dll", "Divine.dll", "Divine.dll.config", "Divine.exe", "Divine.runtimeconfig.json", - } + ) } def download_lslib_if_missing(self, force: bool = False) -> bool: diff --git a/games/baldursgate3/pak_parser.py b/games/baldursgate3/pak_parser.py index 18598a91..a6b9f646 100644 --- a/games/baldursgate3/pak_parser.py +++ b/games/baldursgate3/pak_parser.py @@ -5,9 +5,9 @@ import shutil import subprocess import traceback +from collections.abc import Callable from functools import cached_property from pathlib import Path -from typing import Callable from xml.etree import ElementTree from xml.etree.ElementTree import Element @@ -172,8 +172,7 @@ def _get_metadata_for_file( except OSError as e: qDebug(f"Error accessing file {file_path}: {e}") break - else: - build_pak = False + build_pak = False except OSError as e: qDebug(f"Error accessing file {pak_path}: {e}") build_pak = False diff --git a/games/game_arkhamcity.py b/games/game_arkhamcity.py index 0b8269f4..06cfdc33 100644 --- a/games/game_arkhamcity.py +++ b/games/game_arkhamcity.py @@ -63,8 +63,7 @@ def savesDirectory(self) -> QDir: steamSaves = child.joinpath("200260", "remote") if steamSaves.is_dir(): return QDir(str(steamSaves)) - else: - return docSaves + return docSaves else: return docSaves diff --git a/games/game_baldursgate3.py b/games/game_baldursgate3.py index 6f1ff226..8f03e2dd 100644 --- a/games/game_baldursgate3.py +++ b/games/game_baldursgate3.py @@ -190,7 +190,7 @@ def _on_finished_run(self, exec_path: str, exit_code: int): moved: dict[str, str] = {} for path in self.utils.overwrite_path.rglob("*.log"): try: - moved[str(path)] = str((self.utils.log_dir / path.name)) + moved[str(path)] = str(self.utils.log_dir / path.name) path.replace(self.utils.log_dir / path.name) except PermissionError as e: qDebug(str(e)) diff --git a/games/game_blackandwhite2.py b/games/game_blackandwhite2.py index 5d9f60b3..98a62cc4 100644 --- a/games/game_blackandwhite2.py +++ b/games/game_blackandwhite2.py @@ -278,8 +278,6 @@ def detectGame(self): if installation_path.exists(): self.setGamePath(installation_path.parent) - return - def executables(self) -> list[mobase.ExecutableInfo]: execs = super().executables() diff --git a/games/game_borderlands1.py b/games/game_borderlands1.py index 4b90b513..7f949b5e 100644 --- a/games/game_borderlands1.py +++ b/games/game_borderlands1.py @@ -6,8 +6,8 @@ from ..basic_features import BasicModDataChecker from ..basic_game import BasicGame -_extention_pattern = re.compile("\\.(upk|umap|u|int|dll|exe)$", re.I) -_mapslot_pattern = re.compile("^Mapslot\\d\\d?\\.umap$", re.I) +_extention_pattern = re.compile("\\.(upk|umap|u|int|dll|exe)$", re.IGNORECASE) +_mapslot_pattern = re.compile("^Mapslot\\d\\d?\\.umap$", re.IGNORECASE) _mod_dirs = { "Binaries".casefold(): "/", diff --git a/games/game_cyberpunk2077.py b/games/game_cyberpunk2077.py index 83587969..6816375e 100644 --- a/games/game_cyberpunk2077.py +++ b/games/game_cyberpunk2077.py @@ -62,7 +62,7 @@ def __init__(self): ) -def time_from_seconds(s: int | float) -> str: +def time_from_seconds(s: float) -> str: m, s = divmod(int(s), 60) h, m = divmod(int(m), 60) return f"{h:02}:{m:02}:{s:02}" @@ -496,7 +496,7 @@ def _onAboutToRun(self, app_path_str: str, wd: QDir, args: str) -> bool: return True app_path = Path(app_path_str) if app_path == self._get_redmod_binary(): - if m := re.search(r"%modlist%", args, re.I): + if m := re.search(r"%modlist%", args, re.IGNORECASE): # Manual deployment: replace %modlist% variable ( modlist_path, @@ -592,7 +592,7 @@ def _deploy_redmod(self) -> tuple[bool, int]: ): # Only load order changed: recreate redmod deploys # Fix for redmod not detecting change of load order. - # Faster than -force https://github.com/E1337Kat/cyberpunk2077_ext_redux/issues/297 # noqa: E501 + # Faster than -force https://github.com/E1337Kat/cyberpunk2077_ext_redux/issues/297 qInfo("Redmod order changed, recreate deployed files") self._clean_deployed_redmod(modlist_path) qInfo(f"Deploying redmod with modlist: {modlist_path}") diff --git a/games/game_divinityoriginalsinee.py b/games/game_divinityoriginalsinee.py index fd3836fc..c426547a 100644 --- a/games/game_divinityoriginalsinee.py +++ b/games/game_divinityoriginalsinee.py @@ -1,5 +1,3 @@ -# -*- encoding: utf-8 -*- - import os from pathlib import Path diff --git a/games/game_finalfantasy7rebirth.py b/games/game_finalfantasy7rebirth.py index 5c56cf5c..5a25ece0 100644 --- a/games/game_finalfantasy7rebirth.py +++ b/games/game_finalfantasy7rebirth.py @@ -1,7 +1,7 @@ import math import random +from collections.abc import Iterable from pathlib import Path -from typing import Iterable, List import mobase @@ -139,7 +139,7 @@ def executableForcedLoads(self) -> list[mobase.ExecutableForcedLoadSetting]: def _get_settings(self, key: str) -> mobase.MoVariant: return self._organizer.pluginSetting(self.name(), key) - def mappings(self) -> List[mobase.Mapping]: + def mappings(self) -> list[mobase.Mapping]: mod_path = Path(self.gameDirectory().absolutePath()) / "End/Content/Paks/~Mods" file_path = Path(self.gameDirectory().absolutePath()) / "End/Binaries/Win64" load_enabled = self._get_settings("enforce_mod_load_order") diff --git a/games/game_finalfantasy7remake.py b/games/game_finalfantasy7remake.py index 44dd74f2..9fe9a154 100644 --- a/games/game_finalfantasy7remake.py +++ b/games/game_finalfantasy7remake.py @@ -1,6 +1,6 @@ import math +from collections.abc import Iterable from pathlib import Path -from typing import Iterable, List import mobase @@ -46,7 +46,7 @@ def _active_mod_paths(self) -> Iterable[Path]: if self._organizer.modList().state(mod) & mobase.ModState.ACTIVE: yield mods_parent_path / mod - def _active_mod_mappings(self, mod_paths: List[Path]) -> Iterable[mobase.Mapping]: + def _active_mod_mappings(self, mod_paths: list[Path]) -> Iterable[mobase.Mapping]: if not mod_paths: return pak_priority_digits = math.floor(math.log10(len(mod_paths))) + 1 @@ -65,7 +65,7 @@ def _active_mod_mappings(self, mod_paths: List[Path]) -> Iterable[mobase.Mapping child.is_dir(), ) - def mappings(self) -> List[mobase.Mapping]: + def mappings(self) -> list[mobase.Mapping]: return [ # Not applying load order modifications to overwrites is OK # since the UX is better this way and it will generally work out anyways diff --git a/games/game_masterduel.py b/games/game_masterduel.py index 8c235121..03a94a08 100644 --- a/games/game_masterduel.py +++ b/games/game_masterduel.py @@ -1,5 +1,4 @@ from pathlib import Path -from typing import List, Optional from PyQt6.QtCore import QDir, QFileInfo @@ -41,7 +40,7 @@ def executables(self): def dataDirectory(self) -> QDir: return QDir(self.userDataDir()) - _userDataDirCached: Optional[str] = None + _userDataDirCached: str | None = None # Gets the LocalData/xxxxxxxxx directory. This directory has a different, # unique, 8-character hex name for each user. @@ -58,11 +57,11 @@ def userDataDir(self) -> str: self._userDataDirCached = dir.absolutePath() return self._userDataDirCached - def mappings(self) -> List[mobase.Mapping]: + def mappings(self) -> list[mobase.Mapping]: modsPath = Path(self._organizer.modsPath()) unityMods = self.getUnityDataMods() - mappings: List[mobase.Mapping] = [] + mappings: list[mobase.Mapping] = [] for modName in unityMods: m = mobase.Mapping() diff --git a/games/game_nfshs.py b/games/game_nfshs.py index ef242342..8be93c9f 100644 --- a/games/game_nfshs.py +++ b/games/game_nfshs.py @@ -1,5 +1,3 @@ -# -*- encoding: utf-8 -*- - from PyQt6.QtCore import QFileInfo import mobase diff --git a/games/game_oblivion_remaster.py b/games/game_oblivion_remaster.py index 70459d32..bbdf1d14 100644 --- a/games/game_oblivion_remaster.py +++ b/games/game_oblivion_remaster.py @@ -287,8 +287,9 @@ def write_default_mods(self, profile: QDir): ue4ss_mods_json = QFileInfo(profile.absoluteFilePath("mods.json")) if not ue4ss_mods_txt.exists(): with open(ue4ss_mods_txt.absoluteFilePath(), "w") as mods_txt: - for mod in DEFAULT_UE4SS_MODS: - mods_txt.write(f"{mod['mod_name']} : 1\n") + mods_txt.writelines( + f"{mod['mod_name']} : 1\n" for mod in DEFAULT_UE4SS_MODS + ) if not ue4ss_mods_json.exists(): mods_data: list[UE4SSModInfo] = [] for mod in DEFAULT_UE4SS_MODS: diff --git a/games/game_silenthill2remake.py b/games/game_silenthill2remake.py index 4683a5d1..4de3fc65 100644 --- a/games/game_silenthill2remake.py +++ b/games/game_silenthill2remake.py @@ -1,5 +1,3 @@ -from typing import Tuple - import mobase from ..basic_features import BasicModDataChecker, GlobPatterns @@ -23,7 +21,7 @@ def __init__(self): def _find_tree( self, filetree: mobase.IFileTree - ) -> Tuple[str | None, mobase.FileTreeEntry | None]: + ) -> tuple[str | None, mobase.FileTreeEntry | None]: """ Search the given filetree for a directory name that matches any component of self.mod_path (case-insensitive). diff --git a/games/game_sims4.py b/games/game_sims4.py index e5e7fa21..9302ef05 100644 --- a/games/game_sims4.py +++ b/games/game_sims4.py @@ -1,7 +1,7 @@ from collections.abc import Callable from enum import IntEnum from re import match -from typing import Any, List, Set, cast +from typing import Any, cast from mobase import ( FileTreeEntry, @@ -124,7 +124,7 @@ def fixOrValidateEntry( class TS4ModDataContent(ModDataContent): - def getAllContents(self: ModDataContent) -> List[ModDataContent.Content]: + def getAllContents(self: ModDataContent) -> list[ModDataContent.Content]: return [ ModDataContent.Content( Content.PACKAGE, "Package", ":/MO/gui/content/plugin" @@ -132,8 +132,8 @@ def getAllContents(self: ModDataContent) -> List[ModDataContent.Content]: ModDataContent.Content(Content.SCRIPT, "Script", ":/MO/gui/content/script"), ] - def getContentsFor(self: ModDataContent, filetree: IFileTree) -> List[int]: - contents: Set[int] = set() + def getContentsFor(self: ModDataContent, filetree: IFileTree) -> list[int]: + contents: set[int] = set() def getContentForEntry(path: str, entry: FileTreeEntry): nonlocal contents diff --git a/games/game_tdu.py b/games/game_tdu.py index 5624ff87..6418bf19 100644 --- a/games/game_tdu.py +++ b/games/game_tdu.py @@ -1,5 +1,3 @@ -# -*- encoding: utf-8 -*- - from PyQt6.QtCore import QFileInfo import mobase diff --git a/games/game_tdu2.py b/games/game_tdu2.py index f7fd94f5..bcc3c311 100644 --- a/games/game_tdu2.py +++ b/games/game_tdu2.py @@ -1,5 +1,3 @@ -# -*- encoding: utf-8 -*- - from PyQt6.QtCore import QFileInfo import mobase diff --git a/games/game_thps3.py b/games/game_thps3.py index 52ea07c1..705ab006 100644 --- a/games/game_thps3.py +++ b/games/game_thps3.py @@ -1,5 +1,3 @@ -# -*- encoding: utf-8 -*- - from PyQt6.QtCore import QFileInfo import mobase diff --git a/games/game_thps4.py b/games/game_thps4.py index 7a7ca0b7..5e111c19 100644 --- a/games/game_thps4.py +++ b/games/game_thps4.py @@ -1,5 +1,3 @@ -# -*- encoding: utf-8 -*- - from PyQt6.QtCore import QDir, QFileInfo import mobase diff --git a/games/game_thug.py b/games/game_thug.py index 6a0976f6..c3de133c 100644 --- a/games/game_thug.py +++ b/games/game_thug.py @@ -1,5 +1,3 @@ -# -*- encoding: utf-8 -*- - from PyQt6.QtCore import QDir, QFileInfo import mobase diff --git a/games/game_thug2.py b/games/game_thug2.py index 389e204e..8cd74770 100644 --- a/games/game_thug2.py +++ b/games/game_thug2.py @@ -1,5 +1,3 @@ -# -*- encoding: utf-8 -*- - import os from PyQt6.QtCore import QDir, QFileInfo diff --git a/games/game_tmuf.py b/games/game_tmuf.py index 648da6d1..394eda3a 100644 --- a/games/game_tmuf.py +++ b/games/game_tmuf.py @@ -1,5 +1,3 @@ -# -*- encoding: utf-8 -*- - from __future__ import annotations from PyQt6.QtCore import QFileInfo diff --git a/games/game_valheim.py b/games/game_valheim.py index c402323c..3f8fcc87 100644 --- a/games/game_valheim.py +++ b/games/game_valheim.py @@ -6,7 +6,7 @@ from collections.abc import Collection, Iterable, Mapping, Sequence from dataclasses import dataclass, field from pathlib import Path -from typing import Any, Optional, TextIO +from typing import Any, TextIO from PyQt6.QtCore import QDir @@ -109,7 +109,7 @@ def add( self._table.append(dict.fromkeys(self._column_keys, "")) self._table[-1][k] = str(v) - def print(self, output_file: Optional[TextIO] = None): + def print(self, output_file: TextIO | None = None): if self._table: for line in self._table: print("|", " | ".join(line.values()), "|", file=output_file) @@ -128,11 +128,13 @@ class OverwriteSync: partial_match: PartialMatch = PartialMatch(exclude={"valheim", "mod"}) content_match: ContentMatch = ContentMatch( file_glob_patterns=["*.cfg"], - content_regex=re.compile(r"\A.*plugin (?P.+) v[\d.]+?$", re.I | re.M), + content_regex=re.compile( + r"\A.*plugin (?P.+) v[\d.]+?$", re.IGNORECASE | re.MULTILINE + ), match_group="mod", ) - _debug = DebugTable("overwrite_file | mod | target_path | matches".split(" | ")) + _debug = DebugTable(["overwrite_file", "mod", "target_path", "matches"]) def __init__(self, organizer: mobase.IOrganizer, game: mobase.IPluginGame) -> None: self.organizer = organizer @@ -325,13 +327,10 @@ def init(self, organizer: mobase.IOrganizer) -> bool: "start_server_bepinex.sh", "winhttp.dll", "changelog.txt", - # "InSlimVML", "valheim_Data", "inslimvml.ini", - # "unstripped_managed", - # "AdvancedBuilder", ], ignore=[ @@ -349,7 +348,6 @@ def init(self, organizer: mobase.IOrganizer) -> bool: ], move={ "*_VML.dll": "InSlimVML/Mods/", - # "plugins": "BepInEx/", "Jotunn": "BepInEx/plugins/", "*.dll": "BepInEx/plugins/", @@ -357,13 +355,10 @@ def init(self, organizer: mobase.IOrganizer) -> bool: "Translations": "BepInEx/plugins/", "config": "BepInEx/", "*.cfg": "BepInEx/config/", - # "CustomTextures": "BepInEx/plugins/", "*.png": "BepInEx/plugins/CustomTextures/", - # "Builds": "AdvancedBuilder/", "*.vbuild": "AdvancedBuilder/Builds/", - # "*.assets": "valheim_Data/", }, ) diff --git a/games/game_vampirebloodlines.py b/games/game_vampirebloodlines.py index a63b308d..5c85214e 100644 --- a/games/game_vampirebloodlines.py +++ b/games/game_vampirebloodlines.py @@ -1,5 +1,4 @@ from pathlib import Path -from typing import List from PyQt6.QtCore import QDir @@ -95,7 +94,7 @@ def version(self): def iniFiles(self): return ["autoexec.cfg", "user.cfg"] - def listSaves(self, folder: QDir) -> List[mobase.ISaveGame]: + def listSaves(self, folder: QDir) -> list[mobase.ISaveGame]: ext = self._mappings.savegameExtension.get() return [ VampireSaveGame(path) diff --git a/games/game_witcher1.py b/games/game_witcher1.py index 4d76b588..6e82e284 100644 --- a/games/game_witcher1.py +++ b/games/game_witcher1.py @@ -1,5 +1,5 @@ from pathlib import Path -from typing import BinaryIO, List +from typing import BinaryIO from PyQt6.QtCore import QDir, QFileInfo @@ -82,11 +82,11 @@ def init(self, organizer: mobase.IOrganizer) -> bool: super().init(organizer) return True - def executables(self) -> List[mobase.ExecutableInfo]: + def executables(self) -> list[mobase.ExecutableInfo]: path = QFileInfo(self.gameDirectory(), "System/witcher.exe") return [mobase.ExecutableInfo("The Witcher", path)] - def listSaves(self, folder: QDir) -> List[mobase.ISaveGame]: + def listSaves(self, folder: QDir) -> list[mobase.ISaveGame]: return [ Witcher1SaveGame(path) for path in Path(folder.absolutePath()).glob("*.TheWitcherSave") diff --git a/games/game_witcher2.py b/games/game_witcher2.py index d38bb6bf..b1ecb024 100644 --- a/games/game_witcher2.py +++ b/games/game_witcher2.py @@ -1,5 +1,4 @@ from pathlib import Path -from typing import List from PyQt6.QtCore import QDir @@ -59,7 +58,7 @@ def iniFiles(self): "Input_QWERTZ.ini", ] - def listSaves(self, folder: QDir) -> List[mobase.ISaveGame]: + def listSaves(self, folder: QDir) -> list[mobase.ISaveGame]: ext = self._mappings.savegameExtension.get() return [ Witcher2SaveGame(path) diff --git a/games/game_witcher3.py b/games/game_witcher3.py index 60644dc7..5eda97d5 100644 --- a/games/game_witcher3.py +++ b/games/game_witcher3.py @@ -1,5 +1,4 @@ from pathlib import Path -from typing import List from PyQt6.QtCore import QDir @@ -55,7 +54,7 @@ def looksValid(self, directory: QDir): def iniFiles(self): return ["user.settings", "input.settings"] - def listSaves(self, folder: QDir) -> List[mobase.ISaveGame]: + def listSaves(self, folder: QDir) -> list[mobase.ISaveGame]: ext = self._mappings.savegameExtension.get() return [ Witcher3SaveGame(path) diff --git a/games/game_zeusandposeidon.py b/games/game_zeusandposeidon.py index 33a8c5a6..aa5ded5c 100644 --- a/games/game_zeusandposeidon.py +++ b/games/game_zeusandposeidon.py @@ -1,5 +1,3 @@ -from typing import List, Optional - import mobase from ..basic_game import BasicGame @@ -12,8 +10,8 @@ def __init__(self): def dataLooksValid( self, filetree: mobase.IFileTree ) -> mobase.ModDataChecker.CheckReturn: - folders: List[mobase.IFileTree] = [] - files: List[mobase.FileTreeEntry] = [] + folders: list[mobase.IFileTree] = [] + files: list[mobase.FileTreeEntry] = [] for entry in filetree: if isinstance(entry, mobase.IFileTree): @@ -34,7 +32,7 @@ def dataLooksValid( return mobase.ModDataChecker.INVALID - def fix(self, filetree: mobase.IFileTree) -> Optional[mobase.IFileTree]: + def fix(self, filetree: mobase.IFileTree) -> mobase.IFileTree | None: first_entry = filetree[0] if not isinstance(first_entry, mobase.IFileTree): return None diff --git a/games/oblivion_remaster/game_plugins.py b/games/oblivion_remaster/game_plugins.py index 6777da68..1d8aa54d 100644 --- a/games/oblivion_remaster/game_plugins.py +++ b/games/oblivion_remaster/game_plugins.py @@ -1,5 +1,5 @@ +from collections.abc import Sequence from functools import cmp_to_key -from typing import Sequence from PyQt6.QtCore import ( QByteArray, diff --git a/games/oblivion_remaster/mod_data_checker.py b/games/oblivion_remaster/mod_data_checker.py index 51875b2b..d0058e35 100644 --- a/games/oblivion_remaster/mod_data_checker.py +++ b/games/oblivion_remaster/mod_data_checker.py @@ -40,9 +40,7 @@ def dataLooksValid( status = mobase.ModDataChecker.INVALID # These represent common mod structures that include UE4SS base files. # These should generally be pruned or moved into a Root Builder path. - if filetree.find("ue4ss/UE4SS.dll") is not None: - return mobase.ModDataChecker.FIXABLE - elif ( + if filetree.find("ue4ss/UE4SS.dll") is not None or ( filetree.find("OblivionRemastered/Binaries/Win64/ue4ss/UE4SS.dll") is not None ): diff --git a/games/oblivion_remaster/paks/view.py b/games/oblivion_remaster/paks/view.py index a56b0cdd..8167b5f5 100644 --- a/games/oblivion_remaster/paks/view.py +++ b/games/oblivion_remaster/paks/view.py @@ -1,4 +1,4 @@ -from typing import Iterable +from collections.abc import Iterable from PyQt6.QtCore import QModelIndex, Qt, pyqtSignal from PyQt6.QtGui import QDropEvent diff --git a/games/oblivion_remaster/paks/widget.py b/games/oblivion_remaster/paks/widget.py index efc30386..4977d80b 100644 --- a/games/oblivion_remaster/paks/widget.py +++ b/games/oblivion_remaster/paks/widget.py @@ -101,13 +101,13 @@ def _shake_paks(self, sorted_paks: dict[str, str]) -> list[str]: shaken_paks_p: list[str] = [] paks_list = self.load_paks_list() for pak in paks_list: - if pak in sorted_paks.keys(): + if pak in sorted_paks: if pak.casefold().endswith("_p"): shaken_paks_p.append(pak) else: shaken_paks.append(pak) sorted_paks.pop(pak) - for pak in sorted_paks.keys(): + for pak in sorted_paks: if pak.casefold().endswith("_p"): shaken_paks_p.append(pak) else: diff --git a/games/oblivion_remaster/ue4ss/model.py b/games/oblivion_remaster/ue4ss/model.py index a3804fe7..1ecf232f 100644 --- a/games/oblivion_remaster/ue4ss/model.py +++ b/games/oblivion_remaster/ue4ss/model.py @@ -1,6 +1,7 @@ import json +from collections.abc import Iterable from json import JSONDecodeError -from typing import Any, Iterable +from typing import Any from PyQt6.QtCore import ( QDir, diff --git a/games/oblivion_remaster/ue4ss/view.py b/games/oblivion_remaster/ue4ss/view.py index bb994ca6..2ab0d677 100644 --- a/games/oblivion_remaster/ue4ss/view.py +++ b/games/oblivion_remaster/ue4ss/view.py @@ -1,4 +1,4 @@ -from typing import Iterable +from collections.abc import Iterable from PyQt6.QtCore import QModelIndex, Qt, pyqtSignal from PyQt6.QtGui import QDropEvent diff --git a/games/stalkeranomaly/XRIO.py b/games/stalkeranomaly/XRIO.py index 870f28d1..a3cb3f12 100644 --- a/games/stalkeranomaly/XRIO.py +++ b/games/stalkeranomaly/XRIO.py @@ -1,9 +1,7 @@ -# -*- encoding: utf-8 -*- from __future__ import annotations import io import struct -from typing import Optional, Tuple from .XRMath import IVec3 @@ -16,7 +14,7 @@ def __init__(self, buffer: bytes): def __len__(self) -> int: return len(self._buffer) - def _read(self, size: int) -> Tuple[bytes, int]: + def _read(self, size: int) -> tuple[bytes, int]: pos = min(len(self._buffer), self._pos + size) buffer = self._buffer[self._pos : pos] return (buffer, pos) @@ -107,7 +105,7 @@ def __init__(self, buffer: bytes): super().__init__(buffer) self.last_pos: int = 0 - def find_chunk(self, id: int) -> Optional[int]: + def find_chunk(self, id: int) -> int | None: dw_type = 0 dw_size = 0 success = False @@ -140,7 +138,7 @@ def find_chunk(self, id: int) -> Optional[int]: return dw_size - def open_chunk(self, id: int) -> Optional[XRStream]: + def open_chunk(self, id: int) -> XRStream | None: size = self.find_chunk(id) if size and size != 0: data = self.read(size) diff --git a/games/stalkeranomaly/XRObject.py b/games/stalkeranomaly/XRObject.py index d1eccdb6..feed271e 100644 --- a/games/stalkeranomaly/XRObject.py +++ b/games/stalkeranomaly/XRObject.py @@ -1,8 +1,5 @@ -# -*- encoding: utf-8 -*- - import io from enum import IntFlag -from typing import List from .XRIO import XRReader from .XRMath import IFlag, IVec3 @@ -40,7 +37,7 @@ def __init__(self, name: str = ""): self.version = 0 self.game_type = IFlag(0) self.script_version = 0 - self.client_data: List[int] = [] + self.client_data: list[int] = [] self.spawn_id = 0 self.ini_str = "" diff --git a/games/stalkeranomaly/XRSave.py b/games/stalkeranomaly/XRSave.py index 615aad68..2ffd7d67 100644 --- a/games/stalkeranomaly/XRSave.py +++ b/games/stalkeranomaly/XRSave.py @@ -2,7 +2,7 @@ import struct from datetime import datetime from pathlib import Path -from typing import BinaryIO, Optional +from typing import BinaryIO import lzokay @@ -99,7 +99,7 @@ def splitInfo(self): else: self.save_fmt = "Unknown" - def readFile(self, file: BinaryIO) -> Optional[XRStream]: + def readFile(self, file: BinaryIO) -> XRStream | None: size = self.filepath.stat().st_size if size < 8: return None @@ -125,7 +125,6 @@ def readObject(self, stream: XRStream): actor.read_update(update) if actor: self.player = actor - return None def getFaction(self) -> str: player = self.player diff --git a/origin_utils.py b/origin_utils.py index da050e83..d418de40 100644 --- a/origin_utils.py +++ b/origin_utils.py @@ -1,5 +1,3 @@ -# -*- encoding: utf-8 -*- - # Heavily influenced by https://github.com/erri120/GameFinder import os @@ -101,4 +99,4 @@ def find_games() -> dict[str, Path]: if __name__ == "__main__": games = find_games() for k, v in games.items(): - print("Found game with id {} at {}.".format(k, v)) + print(f"Found game with id {k} at {v}.") diff --git a/steam_utils.py b/steam_utils.py index d1d4a06d..7e83aa8a 100644 --- a/steam_utils.py +++ b/steam_utils.py @@ -17,7 +17,7 @@ def __repr__(self): return str(self) def __str__(self): - return "{} ({})".format(self.appid, self.installdir) + return f"{self.appid} ({self.installdir})" class _AppState(TypedDict): @@ -77,7 +77,7 @@ def __repr__(self): return str(self) def __str__(self): - return "LibraryFolder at {}: {}".format(self.path, self.games) + return f"LibraryFolder at {self.path}: {self.games}" def parse_library_info(library_vdf_path: Path) -> list[LibraryFolder]: @@ -129,7 +129,7 @@ def parse_library_info(library_vdf_path: Path) -> list[LibraryFolder]: library_folders.append(LibraryFolder(Path(path))) except Exception as e: print( - 'Failed to read steam library from "{}", {}'.format(path, repr(e)), + f'Failed to read steam library from "{path}", {e!r}', file=sys.stderr, ) @@ -184,4 +184,4 @@ def find_games() -> dict[str, Path]: if __name__ == "__main__": games = find_games() for k, v in games.items(): - print("Found game with id {} at {}.".format(k, v)) + print(f"Found game with id {k} at {v}.")