mirror of
https://github.com/derrod/legendary.git
synced 2025-08-28 04:21:01 +00:00
[cli] use status queue to print progress
This commit is contained in:
parent
1cf2d7e6e7
commit
c1db2b9f07
|
@ -3,9 +3,11 @@
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import csv
|
import csv
|
||||||
|
import datetime
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import queue
|
||||||
import shlex
|
import shlex
|
||||||
import subprocess
|
import subprocess
|
||||||
import time
|
import time
|
||||||
|
@ -501,13 +503,13 @@ class LegendaryCLI:
|
||||||
logger.info(f'Launch parameters: {shlex.join(params)}')
|
logger.info(f'Launch parameters: {shlex.join(params)}')
|
||||||
logger.info(f'Working directory: {cwd}')
|
logger.info(f'Working directory: {cwd}')
|
||||||
if env:
|
if env:
|
||||||
logger.info('Environment overrides:', env)
|
logger.info(f'Environment overrides: {env}')
|
||||||
else:
|
else:
|
||||||
logger.info(f'Launching {app_name}...')
|
logger.info(f'Launching {app_name}...')
|
||||||
logger.debug(f'Launch parameters: {shlex.join(params)}')
|
logger.debug(f'Launch parameters: {shlex.join(params)}')
|
||||||
logger.debug(f'Working directory: {cwd}')
|
logger.debug(f'Working directory: {cwd}')
|
||||||
if env:
|
if env:
|
||||||
logger.debug('Environment overrides:', env)
|
logger.debug(f'Environment overrides: {env}')
|
||||||
subprocess.Popen(params, cwd=cwd, env=env)
|
subprocess.Popen(params, cwd=cwd, env=env)
|
||||||
|
|
||||||
def install_game(self, args):
|
def install_game(self, args):
|
||||||
|
@ -522,15 +524,15 @@ class LegendaryCLI:
|
||||||
logger.error(f'Update requested for "{args.app_name}", but app not installed!')
|
logger.error(f'Update requested for "{args.app_name}", but app not installed!')
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
|
status_queue = MPQueue()
|
||||||
logger.info('Preparing download...')
|
logger.info('Preparing download...')
|
||||||
# todo use status queue to print progress from CLI
|
|
||||||
# This has become a little ridiculous hasn't it?
|
|
||||||
try:
|
try:
|
||||||
dlm, analysis, game, igame, repair, repair_file = self.core.prepare_download(
|
dlm, analysis, game, igame, repair, repair_file = self.core.prepare_download(
|
||||||
app_name=args.app_name,
|
app_name=args.app_name,
|
||||||
base_path=args.base_path,
|
base_path=args.base_path,
|
||||||
force=args.force,
|
force=args.force,
|
||||||
no_install=args.no_install,
|
no_install=args.no_install,
|
||||||
|
status_q=status_queue,
|
||||||
max_shm=args.shared_memory,
|
max_shm=args.shared_memory,
|
||||||
max_workers=args.max_workers,
|
max_workers=args.max_workers,
|
||||||
game_folder=args.game_folder,
|
game_folder=args.game_folder,
|
||||||
|
@ -578,6 +580,22 @@ class LegendaryCLI:
|
||||||
dlm.proc_debug = args.dlm_debug
|
dlm.proc_debug = args.dlm_debug
|
||||||
|
|
||||||
dlm.start()
|
dlm.start()
|
||||||
|
time.sleep(1)
|
||||||
|
while dlm.is_alive():
|
||||||
|
try:
|
||||||
|
status = status_queue.get(timeout=0.1)
|
||||||
|
logger.info(f'= Progress: {status.progress:.02f}% ({status.processed_chunks}/{status.chunk_tasks}), '
|
||||||
|
f'Running for {str(datetime.timedelta(seconds=status.runtime))}, '
|
||||||
|
f'ETA: {str(datetime.timedelta(seconds=status.estimated_time_left))}')
|
||||||
|
logger.info(f' - Downloaded: {status.total_downloaded / 1024 / 1024:.02f} MiB, '
|
||||||
|
f'Written: {status.total_written / 1024 / 1024:.02f} MiB')
|
||||||
|
logger.info(f' - Cache usage: {status.cache_usage} MiB, active tasks: {status.active_tasks}')
|
||||||
|
logger.info(f' + Download\t- {status.download_speed / 1024 / 1024:.02f} MiB/s (raw) '
|
||||||
|
f'/ {status.download_decompressed_speed / 1024 / 1024:.02f} MiB/s (decompressed)')
|
||||||
|
logger.info(f' + Disk\t- {status.write_speed / 1024 / 1024:.02f} MiB/s (write) / '
|
||||||
|
f'{status.read_speed / 1024 / 1024:.02f} MiB/s (read)')
|
||||||
|
except queue.Empty:
|
||||||
|
pass
|
||||||
dlm.join()
|
dlm.join()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
end_t = time.time()
|
end_t = time.time()
|
||||||
|
|
|
@ -24,8 +24,8 @@ from legendary.lfs.lgndry import LGDLFS
|
||||||
from legendary.utils.lfs import clean_filename, delete_folder, delete_filelist, validate_files
|
from legendary.utils.lfs import clean_filename, delete_folder, delete_filelist, validate_files
|
||||||
from legendary.models.downloading import AnalysisResult, ConditionCheckResult
|
from legendary.models.downloading import AnalysisResult, ConditionCheckResult
|
||||||
from legendary.models.egl import EGLManifest
|
from legendary.models.egl import EGLManifest
|
||||||
from legendary.models.exceptions import *
|
from legendary.models.exceptions import InvalidCredentialsError
|
||||||
from legendary.models.game import *
|
from legendary.models.game import GameAsset, Game, InstalledGame, SaveGameFile, SaveGameStatus, VerifyResult
|
||||||
from legendary.models.json_manifest import JSONManifest
|
from legendary.models.json_manifest import JSONManifest
|
||||||
from legendary.models.manifest import Manifest, ManifestMeta
|
from legendary.models.manifest import Manifest, ManifestMeta
|
||||||
from legendary.models.chunk import Chunk
|
from legendary.models.chunk import Chunk
|
||||||
|
|
|
@ -695,35 +695,30 @@ class DLManager(Process):
|
||||||
total_avail = len(self.sms)
|
total_avail = len(self.sms)
|
||||||
total_used = (num_shared_memory_segments - total_avail) * (self.analysis.biggest_chunk / 1024 / 1024)
|
total_used = (num_shared_memory_segments - total_avail) * (self.analysis.biggest_chunk / 1024 / 1024)
|
||||||
|
|
||||||
if runtime and processed_chunks:
|
try:
|
||||||
rt_hours, runtime = int(runtime // 3600), runtime % 3600
|
|
||||||
rt_minutes, rt_seconds = int(runtime // 60), int(runtime % 60)
|
|
||||||
|
|
||||||
average_speed = processed_chunks / runtime
|
average_speed = processed_chunks / runtime
|
||||||
estimate = (num_chunk_tasks - processed_chunks) / average_speed
|
estimate = (num_chunk_tasks - processed_chunks) / average_speed
|
||||||
hours, estimate = int(estimate // 3600), estimate % 3600
|
except ZeroDivisionError:
|
||||||
minutes, seconds = int(estimate // 60), int(estimate % 60)
|
average_speed = estimate = 0
|
||||||
else:
|
|
||||||
hours = minutes = seconds = 0
|
|
||||||
rt_hours = rt_minutes = rt_seconds = 0
|
|
||||||
|
|
||||||
self.log.info(f'= Progress: {perc:.02f}% ({processed_chunks}/{num_chunk_tasks}), '
|
|
||||||
f'Running for {rt_hours:02d}:{rt_minutes:02d}:{rt_seconds:02d}, '
|
|
||||||
f'ETA: {hours:02d}:{minutes:02d}:{seconds:02d}')
|
|
||||||
self.log.info(f' - Downloaded: {total_dl / 1024 / 1024:.02f} MiB, '
|
|
||||||
f'Written: {total_write / 1024 / 1024:.02f} MiB')
|
|
||||||
self.log.info(f' - Cache usage: {total_used} MiB, active tasks: {self.active_tasks}')
|
|
||||||
self.log.info(f' + Download\t- {dl_speed / 1024 / 1024:.02f} MiB/s (raw) '
|
|
||||||
f'/ {dl_unc_speed / 1024 / 1024:.02f} MiB/s (decompressed)')
|
|
||||||
self.log.info(f' + Disk\t- {w_speed / 1024 / 1024:.02f} MiB/s (write) / '
|
|
||||||
f'{r_speed / 1024 / 1024:.02f} MiB/s (read)')
|
|
||||||
|
|
||||||
|
# TODO set current_filename argument of UIUpdate
|
||||||
# send status update to back to instantiator (if queue exists)
|
# send status update to back to instantiator (if queue exists)
|
||||||
if self.status_queue:
|
if self.status_queue:
|
||||||
try:
|
try:
|
||||||
self.status_queue.put(UIUpdate(
|
self.status_queue.put(UIUpdate(
|
||||||
progress=perc, download_speed=dl_unc_speed, write_speed=w_speed, read_speed=r_speed,
|
progress=perc,
|
||||||
memory_usage=total_used * 1024 * 1024
|
runtime=round(runtime),
|
||||||
|
estimated_time_left=round(estimate),
|
||||||
|
processed_chunks=processed_chunks,
|
||||||
|
chunk_tasks=num_chunk_tasks,
|
||||||
|
total_downloaded=total_dl,
|
||||||
|
total_written=total_write,
|
||||||
|
cache_usage=total_used,
|
||||||
|
active_tasks=self.active_tasks,
|
||||||
|
download_speed=dl_speed,
|
||||||
|
download_decompressed_speed=dl_unc_speed,
|
||||||
|
write_speed=w_speed,
|
||||||
|
read_speed=r_speed,
|
||||||
), timeout=1.0)
|
), timeout=1.0)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.log.warning(f'Failed to send status update to queue: {e!r}')
|
self.log.warning(f'Failed to send status update to queue: {e!r}')
|
||||||
|
|
|
@ -70,14 +70,23 @@ class UIUpdate:
|
||||||
Status update object sent from the manager to the CLI/GUI to update status indicators
|
Status update object sent from the manager to the CLI/GUI to update status indicators
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, progress, download_speed, write_speed, read_speed,
|
def __init__(self, progress, runtime, estimated_time_left, processed_chunks, chunk_tasks,
|
||||||
memory_usage, current_filename=''):
|
total_downloaded, total_written, cache_usage, active_tasks, download_speed,
|
||||||
|
download_decompressed_speed, write_speed, read_speed, current_filename=''):
|
||||||
self.progress = progress
|
self.progress = progress
|
||||||
|
self.runtime = runtime
|
||||||
|
self.estimated_time_left = estimated_time_left
|
||||||
|
self.processed_chunks = processed_chunks
|
||||||
|
self.chunk_tasks = chunk_tasks
|
||||||
|
self.total_downloaded = total_downloaded
|
||||||
|
self.total_written = total_written
|
||||||
|
self.cache_usage = cache_usage
|
||||||
|
self.active_tasks = active_tasks
|
||||||
self.download_speed = download_speed
|
self.download_speed = download_speed
|
||||||
|
self.download_decompressed_speed = download_decompressed_speed
|
||||||
self.write_speed = write_speed
|
self.write_speed = write_speed
|
||||||
self.read_speed = read_speed
|
self.read_speed = read_speed
|
||||||
self.current_filename = current_filename
|
self.current_filename = current_filename
|
||||||
self.memory_usage = memory_usage
|
|
||||||
|
|
||||||
|
|
||||||
class SharedMemorySegment:
|
class SharedMemorySegment:
|
||||||
|
|
Loading…
Reference in a new issue