1
0
Fork 0
mirror of synced 2024-06-02 10:44:40 +12:00

Merge pull request #333 from loathingKernel/next

Update legendary to 0.20.34
This commit is contained in:
Stelios Tsampas 2023-12-10 13:57:58 +02:00 committed by GitHub
commit bf1392e25f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 42 additions and 103 deletions

View file

@ -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:

View file

@ -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]

View file

@ -1,2 +1,2 @@
__version__ = "1.10.6"
__version__ = "1.10.7"
__codename__ = "Garlic Crab"

View file

@ -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

View file

@ -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

View file

@ -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()

View file

@ -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

View file

@ -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())

View file

@ -3,5 +3,5 @@ requests
PyQt5
QtAwesome
setuptools
legendary-gl>=0.20.33
legendary-gl>=0.20.34
pywin32; platform_system == "Windows"

View file

@ -7,7 +7,7 @@ with open("README.md", "r") as fh:
requirements = [
"requests<3.0",
"legendary-gl>=0.20.33",
"legendary-gl>=0.20.34",
"setuptools",
"wheel",
"PyQt5",