1
0
Fork 0
mirror of synced 2024-06-26 18:20:50 +12:00

Lgndr: Use custom wrapped decorator to wrap LegendaryCLI functions

Lgndr: Add `get_boolean_choice` to relevant args dataclasses
Lgndr: Move mock functions to `api_monkeys`

InstallDialog: Add status queue to prepare_overlay_install arguments, fixes missing download stats
This commit is contained in:
loathingKernel 2022-07-11 13:22:17 +03:00
parent 7aded95a1f
commit aeb149a3e9
5 changed files with 62 additions and 36 deletions

View file

@ -9,7 +9,7 @@ from PyQt5.QtGui import QCloseEvent, QKeyEvent
from PyQt5.QtWidgets import QDialog, QFileDialog, QCheckBox from PyQt5.QtWidgets import QDialog, QFileDialog, QCheckBox
from rare.lgndr.api_arguments import LgndrInstallGameArgs from rare.lgndr.api_arguments import LgndrInstallGameArgs
from rare.lgndr.cli import LegendaryCLI from rare.lgndr.api_exception import LgndrException
from rare.lgndr.core import LegendaryCore from rare.lgndr.core import LegendaryCore
from legendary.models.downloading import ConditionCheckResult from legendary.models.downloading import ConditionCheckResult
from legendary.models.game import Game from legendary.models.game import Game
@ -312,7 +312,7 @@ class InstallInfoWorker(QRunnable):
cli = LegendaryCLISingleton() cli = LegendaryCLISingleton()
download = InstallDownloadModel( download = InstallDownloadModel(
# *self.core.prepare_download( # *self.core.prepare_download(
*cli.prepare_install(LgndrInstallGameArgs( *cli.install_game(LgndrInstallGameArgs(
app_name=self.dl_item.options.app_name, app_name=self.dl_item.options.app_name,
base_path=self.dl_item.options.base_path, base_path=self.dl_item.options.base_path,
force=self.dl_item.options.force, force=self.dl_item.options.force,
@ -347,6 +347,7 @@ class InstallInfoWorker(QRunnable):
dlm, analysis, igame = self.core.prepare_overlay_install( dlm, analysis, igame = self.core.prepare_overlay_install(
path=self.dl_item.options.base_path, path=self.dl_item.options.base_path,
status_q=self.dl_item.status_q,
) )
download = InstallDownloadModel( download = InstallDownloadModel(
@ -363,6 +364,8 @@ class InstallInfoWorker(QRunnable):
self.signals.result.emit(download) self.signals.result.emit(download)
else: else:
self.signals.failed.emit("\n".join(str(i) for i in download.res.failures)) self.signals.failed.emit("\n".join(str(i) for i in download.res.failures))
except LgndrException as ret:
self.signals.failed.emit(ret.message)
except Exception as e: except Exception as e:
self.signals.failed.emit(str(e)) self.signals.failed.emit(str(e))
self.signals.finished.emit() self.signals.finished.emit()

View file

@ -2,6 +2,8 @@ from dataclasses import dataclass
from multiprocessing import Queue from multiprocessing import Queue
from typing import Callable, List from typing import Callable, List
from .api_monkeys import get_boolean_choice
@dataclass(kw_only=True) @dataclass(kw_only=True)
class LgndrCommonArgs: class LgndrCommonArgs:
@ -21,6 +23,8 @@ class LgndrImportGameArgs:
skip_dlcs: bool = False skip_dlcs: bool = False
with_dlcs: bool = False with_dlcs: bool = False
yes: bool = False yes: bool = False
# Rare: Extra arguments
get_boolean_choice: Callable[[str], bool] = get_boolean_choice
@dataclass @dataclass
@ -65,6 +69,7 @@ class LgndrInstallGameArgs:
disable_https: bool = False disable_https: bool = False
yes: bool = True yes: bool = True
# Rare: Extra arguments # Rare: Extra arguments
get_boolean_choice: Callable[[str], bool] = get_boolean_choice
sdl_prompt: Callable[[str, str], List[str]] = lambda a0, a1: [] sdl_prompt: Callable[[str, str], List[str]] = lambda a0, a1: []
verify_stdout: Callable[[int, int, float, float], None] = lambda a0, a1, a2, a3: print( verify_stdout: Callable[[int, int, float, float], None] = lambda a0, a1, a2, a3: print(
f"Verification progress: {a0}/{a1} ({a2:.01f}%) [{a3:.1f} MiB/s]\t\r" f"Verification progress: {a0}/{a1} ({a2:.01f}%) [{a3:.1f} MiB/s]\t\r"

21
rare/lgndr/api_monkeys.py Normal file
View file

@ -0,0 +1,21 @@
import logging
from PyQt5.QtWidgets import QMessageBox, QLabel
def get_boolean_choice(a0):
choice = QMessageBox.question(None, "Import DLCs?", a0)
return True if choice == QMessageBox.StandardButton.Yes else False
def return_exit(__status):
return __status
class UILogHandler(logging.Handler):
def __init__(self, dest: QLabel):
super(UILogHandler, self).__init__()
self.widget = dest
def emit(self, record: logging.LogRecord) -> None:
self.widget.setText(record.getMessage())

View file

@ -1,7 +1,8 @@
import functools
import os import os
import logging import logging
import time import time
from typing import Optional, Union from typing import Optional, Union, overload
import legendary.cli import legendary.cli
from PyQt5.QtWidgets import QLabel, QMessageBox from PyQt5.QtWidgets import QLabel, QMessageBox
@ -15,25 +16,12 @@ from .core import LegendaryCore
from .manager import DLManager from .manager import DLManager
from .api_arguments import LgndrInstallGameArgs, LgndrImportGameArgs, LgndrVerifyGameArgs from .api_arguments import LgndrInstallGameArgs, LgndrImportGameArgs, LgndrVerifyGameArgs
from .api_exception import LgndrException, LgndrLogHandler from .api_exception import LgndrException, LgndrLogHandler
from .api_monkeys import return_exit, get_boolean_choice
def get_boolean_choice(message):
choice = QMessageBox.question(None, "Import DLCs?", message)
return True if choice == QMessageBox.StandardButton.Yes else False
class UILogHandler(logging.Handler):
def __init__(self, dest: QLabel):
super(UILogHandler, self).__init__()
self.widget = dest
def emit(self, record: logging.LogRecord) -> None:
self.widget.setText(record.getMessage())
class LegendaryCLI(legendary.cli.LegendaryCLI): class LegendaryCLI(legendary.cli.LegendaryCLI):
def __init__(self, override_config=None, api_timeout=None): def __init__(self, override_config=None, api_timeout=None):
self.core = LegendaryCore(override_config) self.core = LegendaryCore(override_config, timeout=api_timeout)
self.logger = logging.getLogger('cli') self.logger = logging.getLogger('cli')
self.logging_queue = None self.logging_queue = None
self.handler = LgndrLogHandler() self.handler = LgndrLogHandler()
@ -42,16 +30,30 @@ class LegendaryCLI(legendary.cli.LegendaryCLI):
def resolve_aliases(self, name): def resolve_aliases(self, name):
return super(LegendaryCLI, self)._resolve_aliases(name) return super(LegendaryCLI, self)._resolve_aliases(name)
def prepare_install(self, args: LgndrInstallGameArgs) -> (DLManager, AnalysisResult, InstalledGame, Game, bool, Optional[str], ConditionCheckResult): @staticmethod
old_choice = legendary.cli.get_boolean_choice def wrapped(func):
legendary.cli.get_boolean_choice = get_boolean_choice
try:
return self.install_game(args)
except LgndrException as ret:
raise ret
finally:
legendary.cli.get_boolean_choice = old_choice
@functools.wraps(func)
def inner(self, args, *oargs, **kwargs):
old_exit = legendary.cli.exit
legendary.cli.exit = return_exit
old_choice = legendary.cli.get_boolean_choice
if hasattr(args, 'get_boolean_choice') and args.get_boolean_choice is not None:
legendary.cli.get_boolean_choice = args.get_boolean_choice
try:
return func(self, args, *oargs, **kwargs)
except LgndrException as ret:
print(f'Caught exception in wrapped function {ret.message}')
raise ret
finally:
legendary.cli.get_boolean_choice = old_choice
legendary.cli.exit = old_exit
return inner
@wrapped
def install_game(self, args: LgndrInstallGameArgs) -> (DLManager, AnalysisResult, InstalledGame, Game, bool, Optional[str], ConditionCheckResult): def install_game(self, args: LgndrInstallGameArgs) -> (DLManager, AnalysisResult, InstalledGame, Game, bool, Optional[str], ConditionCheckResult):
args.app_name = self._resolve_aliases(args.app_name) args.app_name = self._resolve_aliases(args.app_name)
if self.core.is_installed(args.app_name): if self.core.is_installed(args.app_name):
@ -224,6 +226,7 @@ class LegendaryCLI(legendary.cli.LegendaryCLI):
def _handle_postinstall(self, postinstall, igame, yes=False): def _handle_postinstall(self, postinstall, igame, yes=False):
super(LegendaryCLI, self)._handle_postinstall(postinstall, igame, yes) super(LegendaryCLI, self)._handle_postinstall(postinstall, igame, yes)
@wrapped
def uninstall_game(self, args): def uninstall_game(self, args):
super(LegendaryCLI, self).uninstall_game(args) super(LegendaryCLI, self).uninstall_game(args)
@ -336,12 +339,6 @@ class LegendaryCLI(legendary.cli.LegendaryCLI):
logger.info(f'Run "legendary repair {args.app_name}" to repair your game installation.') logger.info(f'Run "legendary repair {args.app_name}" to repair your game installation.')
return False, len(failed), len(missing) return False, len(failed), len(missing)
@wrapped
def import_game(self, args: LgndrImportGameArgs): def import_game(self, args: LgndrImportGameArgs):
old_choice = legendary.cli.get_boolean_choice super(LegendaryCLI, self).import_game(args)
legendary.cli.get_boolean_choice = get_boolean_choice
try:
super(LegendaryCLI, self).import_game(args)
except LgndrException as ret:
raise ret
finally:
legendary.cli.get_boolean_choice = old_choice

View file

@ -26,7 +26,7 @@ def LegendaryCLISingleton(init: bool = False) -> LegendaryCLI:
if _legendary_cli_signleton is None and not init: if _legendary_cli_signleton is None and not init:
raise RuntimeError("Uninitialized use of LegendaryCLISingleton") raise RuntimeError("Uninitialized use of LegendaryCLISingleton")
if _legendary_cli_signleton is None: if _legendary_cli_signleton is None:
_legendary_cli_signleton = LegendaryCLI() _legendary_cli_signleton = LegendaryCLI(override_config=None, api_timeout=10)
return _legendary_cli_signleton return _legendary_cli_signleton