mirror of
https://github.com/derrod/legendary.git
synced 2025-08-26 20:11:04 +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 csv
|
||||
import datetime
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import queue
|
||||
import shlex
|
||||
import subprocess
|
||||
import time
|
||||
|
@ -501,13 +503,13 @@ class LegendaryCLI:
|
|||
logger.info(f'Launch parameters: {shlex.join(params)}')
|
||||
logger.info(f'Working directory: {cwd}')
|
||||
if env:
|
||||
logger.info('Environment overrides:', env)
|
||||
logger.info(f'Environment overrides: {env}')
|
||||
else:
|
||||
logger.info(f'Launching {app_name}...')
|
||||
logger.debug(f'Launch parameters: {shlex.join(params)}')
|
||||
logger.debug(f'Working directory: {cwd}')
|
||||
if env:
|
||||
logger.debug('Environment overrides:', env)
|
||||
logger.debug(f'Environment overrides: {env}')
|
||||
subprocess.Popen(params, cwd=cwd, env=env)
|
||||
|
||||
def install_game(self, args):
|
||||
|
@ -522,15 +524,15 @@ class LegendaryCLI:
|
|||
logger.error(f'Update requested for "{args.app_name}", but app not installed!')
|
||||
exit(1)
|
||||
|
||||
status_queue = MPQueue()
|
||||
logger.info('Preparing download...')
|
||||
# todo use status queue to print progress from CLI
|
||||
# This has become a little ridiculous hasn't it?
|
||||
try:
|
||||
dlm, analysis, game, igame, repair, repair_file = self.core.prepare_download(
|
||||
app_name=args.app_name,
|
||||
base_path=args.base_path,
|
||||
force=args.force,
|
||||
no_install=args.no_install,
|
||||
status_q=status_queue,
|
||||
max_shm=args.shared_memory,
|
||||
max_workers=args.max_workers,
|
||||
game_folder=args.game_folder,
|
||||
|
@ -578,6 +580,22 @@ class LegendaryCLI:
|
|||
dlm.proc_debug = args.dlm_debug
|
||||
|
||||
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()
|
||||
except Exception as e:
|
||||
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.models.downloading import AnalysisResult, ConditionCheckResult
|
||||
from legendary.models.egl import EGLManifest
|
||||
from legendary.models.exceptions import *
|
||||
from legendary.models.game import *
|
||||
from legendary.models.exceptions import InvalidCredentialsError
|
||||
from legendary.models.game import GameAsset, Game, InstalledGame, SaveGameFile, SaveGameStatus, VerifyResult
|
||||
from legendary.models.json_manifest import JSONManifest
|
||||
from legendary.models.manifest import Manifest, ManifestMeta
|
||||
from legendary.models.chunk import Chunk
|
||||
|
|
|
@ -695,35 +695,30 @@ class DLManager(Process):
|
|||
total_avail = len(self.sms)
|
||||
total_used = (num_shared_memory_segments - total_avail) * (self.analysis.biggest_chunk / 1024 / 1024)
|
||||
|
||||
if runtime and processed_chunks:
|
||||
rt_hours, runtime = int(runtime // 3600), runtime % 3600
|
||||
rt_minutes, rt_seconds = int(runtime // 60), int(runtime % 60)
|
||||
|
||||
try:
|
||||
average_speed = processed_chunks / runtime
|
||||
estimate = (num_chunk_tasks - processed_chunks) / average_speed
|
||||
hours, estimate = int(estimate // 3600), estimate % 3600
|
||||
minutes, seconds = int(estimate // 60), int(estimate % 60)
|
||||
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)')
|
||||
except ZeroDivisionError:
|
||||
average_speed = estimate = 0
|
||||
|
||||
# TODO set current_filename argument of UIUpdate
|
||||
# send status update to back to instantiator (if queue exists)
|
||||
if self.status_queue:
|
||||
try:
|
||||
self.status_queue.put(UIUpdate(
|
||||
progress=perc, download_speed=dl_unc_speed, write_speed=w_speed, read_speed=r_speed,
|
||||
memory_usage=total_used * 1024 * 1024
|
||||
progress=perc,
|
||||
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)
|
||||
except Exception as e:
|
||||
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
|
||||
"""
|
||||
|
||||
def __init__(self, progress, download_speed, write_speed, read_speed,
|
||||
memory_usage, current_filename=''):
|
||||
def __init__(self, progress, runtime, estimated_time_left, processed_chunks, chunk_tasks,
|
||||
total_downloaded, total_written, cache_usage, active_tasks, download_speed,
|
||||
download_decompressed_speed, write_speed, read_speed, current_filename=''):
|
||||
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_decompressed_speed = download_decompressed_speed
|
||||
self.write_speed = write_speed
|
||||
self.read_speed = read_speed
|
||||
self.current_filename = current_filename
|
||||
self.memory_usage = memory_usage
|
||||
|
||||
|
||||
class SharedMemorySegment:
|
||||
|
|
Loading…
Reference in a new issue