Merge pull request #333 from loathingKernel/next
Update legendary to 0.20.34
This commit is contained in:
commit
bf1392e25f
|
@ -21,7 +21,7 @@ AppDir:
|
|||
id: io.github.dummerle.rare
|
||||
name: Rare
|
||||
icon: Rare
|
||||
version: 1.10.6
|
||||
version: 1.10.7
|
||||
exec: usr/bin/python3
|
||||
exec_args: $APPDIR/usr/src/__main__.py $@
|
||||
apt:
|
||||
|
|
|
@ -12,7 +12,7 @@ force-exclude = '''
|
|||
|
||||
[tool.poetry]
|
||||
name = "rare"
|
||||
version = "1.10.6"
|
||||
version = "1.10.7"
|
||||
description = "A GUI for Legendary"
|
||||
authors = ["Dummerle"]
|
||||
license = "GPL3"
|
||||
|
@ -31,7 +31,7 @@ pywebview = [
|
|||
{ version = "^3.6.3", extras = ["gtk"], platform = "linux", optional = true },
|
||||
{ version = "^3.6.3", extras = ["gtk"], platform = "freebsd", optional = true },
|
||||
]
|
||||
legendary-gl = "^0.20.33"
|
||||
legendary-gl = "^0.20.34"
|
||||
typing-extensions = "^4.3.0"
|
||||
|
||||
[tool.poetry.scripts]
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
__version__ = "1.10.6"
|
||||
__version__ = "1.10.7"
|
||||
__codename__ = "Garlic Crab"
|
||||
|
|
|
@ -43,8 +43,12 @@ class LegendaryCLI(LegendaryCLIReal):
|
|||
def unlock_installed(func):
|
||||
@functools.wraps(func)
|
||||
def unlock(self, *args, **kwargs):
|
||||
ret = func(self, *args, **kwargs)
|
||||
self.core.lgd._installed_lock.release(force=True)
|
||||
try:
|
||||
ret = func(self, *args, **kwargs)
|
||||
except Exception as e:
|
||||
raise e
|
||||
finally:
|
||||
self.core.lgd._installed_lock.release(force=True)
|
||||
return ret
|
||||
return unlock
|
||||
|
||||
|
@ -201,7 +205,8 @@ class LegendaryCLI(LegendaryCLIReal):
|
|||
disable_delta=args.disable_delta,
|
||||
override_delta_manifest=args.override_delta_manifest,
|
||||
preferred_cdn=args.preferred_cdn,
|
||||
disable_https=args.disable_https)
|
||||
disable_https=args.disable_https,
|
||||
bind_ip=args.bind_ip)
|
||||
|
||||
# game is either up-to-date or hasn't changed, so we have nothing to do
|
||||
if not analysis.dl_size and not game.is_dlc:
|
||||
|
@ -400,7 +405,7 @@ class LegendaryCLI(LegendaryCLIReal):
|
|||
return
|
||||
|
||||
if os.name == 'nt' and igame.uninstaller and not args.skip_uninstaller:
|
||||
self._handle_uninstaller(igame, args)
|
||||
self._handle_uninstaller(igame, args.yes, args)
|
||||
|
||||
try:
|
||||
if not igame.is_dlc:
|
||||
|
@ -420,10 +425,9 @@ class LegendaryCLI(LegendaryCLIReal):
|
|||
logger.warning(f'Removing game failed: {e!r}, please remove {igame.install_path} manually.')
|
||||
return
|
||||
|
||||
def _handle_uninstaller(self, igame: InstalledGame, args: LgndrUninstallGameArgs):
|
||||
def _handle_uninstaller(self, igame: InstalledGame, yes=False, args: LgndrUninstallGameArgs = None):
|
||||
# Override logger for the local context to use message as part of the indirect return value
|
||||
logger = LgndrIndirectLogger(args.indirect_status, self.logger, logging.WARNING)
|
||||
yes = args.yes
|
||||
get_boolean_choice = args.get_boolean_choice_handler
|
||||
# def get_boolean_choice(x, default): return True
|
||||
# noinspection PyShadowingBuiltins
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
import functools
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
from datetime import datetime
|
||||
from multiprocessing import Queue
|
||||
from uuid import uuid4
|
||||
from requests.exceptions import HTTPError, ConnectionError
|
||||
|
||||
# On Windows the monkeypatching of `run_real` below doesn't work like on Linux
|
||||
# This has the side effect of emitting the UIUpdate in DownloadThread complaining with a TypeError
|
||||
|
@ -14,12 +13,11 @@ from legendary.core import LegendaryCore as LegendaryCoreReal
|
|||
from legendary.lfs.utils import delete_folder
|
||||
from legendary.models.downloading import AnalysisResult
|
||||
from legendary.models.egl import EGLManifest
|
||||
from legendary.models.exceptions import InvalidCredentialsError
|
||||
from legendary.models.game import Game, InstalledGame
|
||||
from legendary.models.manifest import ManifestMeta
|
||||
|
||||
from rare.lgndr.downloader.mp.manager import DLManager
|
||||
from rare.lgndr.glue.exception import LgndrException, LgndrCoreLogHandler
|
||||
from rare.lgndr.glue.exception import LgndrException, LgndrLogHandler
|
||||
|
||||
legendary.core.DLManager = DLManager
|
||||
|
||||
|
@ -29,87 +27,22 @@ class LegendaryCore(LegendaryCoreReal):
|
|||
|
||||
def __init__(self, override_config=None, timeout=10.0):
|
||||
super(LegendaryCore, self).__init__(override_config=override_config, timeout=timeout)
|
||||
self.handler = LgndrCoreLogHandler()
|
||||
self.handler = LgndrLogHandler(logging.CRITICAL)
|
||||
self.log.addHandler(self.handler)
|
||||
|
||||
@staticmethod
|
||||
def unlock_installed(func):
|
||||
@functools.wraps(func)
|
||||
def unlock(self, *args, **kwargs):
|
||||
ret = func(self, *args, **kwargs)
|
||||
self.lgd._installed_lock.release(force=True)
|
||||
try:
|
||||
ret = func(self, *args, **kwargs)
|
||||
except Exception as e:
|
||||
raise e
|
||||
finally:
|
||||
self.lgd._installed_lock.release(force=True)
|
||||
return ret
|
||||
return unlock
|
||||
|
||||
def _login(self, lock, force_refresh=False) -> bool:
|
||||
"""
|
||||
Attempts logging in with existing credentials.
|
||||
|
||||
raises ValueError if no existing credentials or InvalidCredentialsError if the API return an error
|
||||
"""
|
||||
if not lock.data:
|
||||
raise ValueError('No saved credentials')
|
||||
elif self.logged_in and lock.data['expires_at']:
|
||||
dt_exp = datetime.fromisoformat(lock.data['expires_at'][:-1])
|
||||
dt_now = datetime.utcnow()
|
||||
td = dt_now - dt_exp
|
||||
|
||||
# if session still has at least 10 minutes left we can re-use it.
|
||||
if dt_exp > dt_now and abs(td.total_seconds()) > 600:
|
||||
return True
|
||||
else:
|
||||
self.logged_in = False
|
||||
|
||||
# run update check
|
||||
if self.update_check_enabled():
|
||||
try:
|
||||
self.check_for_updates()
|
||||
except Exception as e:
|
||||
self.log.warning(f'Checking for Legendary updates failed: {e!r}')
|
||||
else:
|
||||
self.apply_lgd_config()
|
||||
|
||||
# check for overlay updates
|
||||
if self.is_overlay_installed():
|
||||
try:
|
||||
self.check_for_overlay_updates()
|
||||
except Exception as e:
|
||||
self.log.warning(f'Checking for EOS Overlay updates failed: {e!r}')
|
||||
|
||||
if lock.data['expires_at'] and not force_refresh:
|
||||
dt_exp = datetime.fromisoformat(lock.data['expires_at'][:-1])
|
||||
dt_now = datetime.utcnow()
|
||||
td = dt_now - dt_exp
|
||||
|
||||
# if session still has at least 10 minutes left we can re-use it.
|
||||
if dt_exp > dt_now and abs(td.total_seconds()) > 600:
|
||||
self.log.info('Trying to re-use existing login session...')
|
||||
try:
|
||||
self.egs.resume_session(lock.data)
|
||||
self.logged_in = True
|
||||
return True
|
||||
except InvalidCredentialsError as e:
|
||||
self.log.warning(f'Resuming failed due to invalid credentials: {e!r}')
|
||||
except Exception as e:
|
||||
self.log.warning(f'Resuming failed for unknown reason: {e!r}')
|
||||
# If verify fails just continue the normal authentication process
|
||||
self.log.info('Falling back to using refresh token...')
|
||||
|
||||
try:
|
||||
self.log.info('Logging in...')
|
||||
userdata = self.egs.start_session(lock.data['refresh_token'])
|
||||
except InvalidCredentialsError:
|
||||
self.log.error('Stored credentials are no longer valid! Please login again.')
|
||||
lock.clear()
|
||||
return False
|
||||
except (HTTPError, ConnectionError) as e:
|
||||
self.log.error(f'HTTP request for login failed: {e!r}, please try again later.')
|
||||
return False
|
||||
|
||||
lock.data = userdata
|
||||
self.logged_in = True
|
||||
return True
|
||||
|
||||
# skip_sync defaults to false but since Rare is persistent, skip by default
|
||||
# def get_installed_game(self, app_name, skip_sync=True) -> InstalledGame:
|
||||
# return super(LegendaryCore, self).get_installed_game(app_name, skip_sync)
|
||||
|
@ -125,7 +58,7 @@ class LegendaryCore(LegendaryCoreReal):
|
|||
repair: bool = False, repair_use_latest: bool = False,
|
||||
disable_delta: bool = False, override_delta_manifest: str = '',
|
||||
egl_guid: str = '', preferred_cdn: str = None,
|
||||
disable_https: bool = False) -> (DLManager, AnalysisResult, ManifestMeta):
|
||||
disable_https: bool = False, bind_ip: str = None) -> (DLManager, AnalysisResult, ManifestMeta):
|
||||
dlm, analysis, igame = super(LegendaryCore, self).prepare_download(
|
||||
game=game, base_game=base_game, base_path=base_path,
|
||||
status_q=status_q, max_shm=max_shm, max_workers=max_workers,
|
||||
|
@ -138,7 +71,7 @@ class LegendaryCore(LegendaryCoreReal):
|
|||
repair=repair, repair_use_latest=repair_use_latest,
|
||||
disable_delta=disable_delta, override_delta_manifest=override_delta_manifest,
|
||||
egl_guid=egl_guid, preferred_cdn=preferred_cdn,
|
||||
disable_https=disable_https
|
||||
disable_https=disable_https, bind_ip=bind_ip,
|
||||
)
|
||||
# lk: monkeypatch run_real (the method that emits the stats) into DLManager
|
||||
# pylint: disable=E1111
|
||||
|
|
|
@ -40,10 +40,15 @@ class DLManager(DLManagerReal):
|
|||
self.writer_result_q = MPQueue(-1)
|
||||
|
||||
self.log.info(f'Starting download workers...')
|
||||
|
||||
bind_ip = None
|
||||
for i in range(self.max_workers):
|
||||
if self.bind_ips:
|
||||
bind_ip = self.bind_ips[i % len(self.bind_ips)]
|
||||
|
||||
w = DLWorker(f'DLWorker {i + 1}', self.dl_worker_queue, self.dl_result_q,
|
||||
self.shared_memory.name, logging_queue=self.logging_queue,
|
||||
dl_timeout=self.dl_timeout)
|
||||
dl_timeout=self.dl_timeout, bind_addr=bind_ip)
|
||||
self.children.append(w)
|
||||
w.start()
|
||||
|
||||
|
|
|
@ -86,6 +86,7 @@ class LgndrInstallGameArgs:
|
|||
reset_sdl: bool = False
|
||||
skip_sdl: bool = False
|
||||
disable_https: bool = False
|
||||
bind_ip: str = ""
|
||||
# FIXME: move to LgndrInstallGameRealArgs
|
||||
skip_dlcs: bool = False
|
||||
with_dlcs: bool = False
|
||||
|
|
|
@ -14,19 +14,15 @@ class LgndrWarning(RuntimeWarning):
|
|||
super(LgndrWarning, self).__init__(self.message)
|
||||
|
||||
|
||||
class LgndrCLILogHandler(logging.Handler):
|
||||
def emit(self, record: logging.LogRecord) -> None:
|
||||
# lk: FATAL is the same as CRITICAL
|
||||
if record.levelno == logging.ERROR or record.levelno == logging.CRITICAL:
|
||||
raise LgndrException(record.getMessage())
|
||||
# if record.levelno < logging.ERROR or record.levelno == logging.WARNING:
|
||||
# warnings.warn(record.getMessage())
|
||||
# Minimum exception levels per class to get back useful error strings
|
||||
# CLI: ERROR
|
||||
# Core: CRITICAL (FATAL)
|
||||
class LgndrLogHandler(logging.Handler):
|
||||
def __init__(self, level=logging.NOTSET):
|
||||
super().__init__(level=level)
|
||||
|
||||
|
||||
class LgndrCoreLogHandler(logging.Handler):
|
||||
def emit(self, record: logging.LogRecord) -> None:
|
||||
# lk: FATAL is the same as CRITICAL
|
||||
if record.levelno == logging.CRITICAL:
|
||||
if record.levelno >= self.level:
|
||||
raise LgndrException(record.getMessage())
|
||||
# if record.levelno < logging.CRITICAL:
|
||||
# if self.level > record.levelno >= logging.WARNING:
|
||||
# warnings.warn(record.getMessage())
|
||||
|
|
|
@ -3,5 +3,5 @@ requests
|
|||
PyQt5
|
||||
QtAwesome
|
||||
setuptools
|
||||
legendary-gl>=0.20.33
|
||||
legendary-gl>=0.20.34
|
||||
pywin32; platform_system == "Windows"
|
||||
|
|
Loading…
Reference in a new issue