Merge pull request #378 from exislow/374-remove-when-downloading-much-files
👷 CLI: Download list is scrolling vertically and overall progress is …
This commit is contained in:
+68
-41
@@ -4,9 +4,16 @@ from pathlib import Path
|
|||||||
from typing import Annotated, Optional
|
from typing import Annotated, Optional
|
||||||
|
|
||||||
import typer
|
import typer
|
||||||
|
from rich.console import Group
|
||||||
from rich.live import Live
|
from rich.live import Live
|
||||||
from rich.panel import Panel
|
from rich.progress import (
|
||||||
from rich.progress import BarColumn, Console, Progress, SpinnerColumn, TextColumn
|
BarColumn,
|
||||||
|
Console,
|
||||||
|
Progress,
|
||||||
|
SpinnerColumn,
|
||||||
|
TaskProgressColumn,
|
||||||
|
TextColumn,
|
||||||
|
)
|
||||||
from rich.table import Table
|
from rich.table import Table
|
||||||
|
|
||||||
from tidal_dl_ng import __version__
|
from tidal_dl_ng import __version__
|
||||||
@@ -58,10 +65,20 @@ def _download(ctx: typer.Context, urls: list[str], try_login: bool = True) -> bo
|
|||||||
# Create initial objects.
|
# Create initial objects.
|
||||||
settings: Settings = Settings()
|
settings: Settings = Settings()
|
||||||
progress: Progress = Progress(
|
progress: Progress = Progress(
|
||||||
"{task.description}",
|
TextColumn("[progress.description]{task.description}"),
|
||||||
SpinnerColumn(),
|
SpinnerColumn(),
|
||||||
BarColumn(),
|
BarColumn(),
|
||||||
TextColumn("[progress.percentage]{task.percentage:>3.0f}%"),
|
TaskProgressColumn(),
|
||||||
|
refresh_per_second=20,
|
||||||
|
auto_refresh=True,
|
||||||
|
expand=True,
|
||||||
|
transient=False, # Prevent progress from disappearing
|
||||||
|
)
|
||||||
|
progress_overall = Progress(
|
||||||
|
TextColumn("[progress.description]{task.description}"),
|
||||||
|
SpinnerColumn(),
|
||||||
|
BarColumn(),
|
||||||
|
TaskProgressColumn(),
|
||||||
refresh_per_second=20,
|
refresh_per_second=20,
|
||||||
auto_refresh=True,
|
auto_refresh=True,
|
||||||
expand=True,
|
expand=True,
|
||||||
@@ -74,59 +91,69 @@ def _download(ctx: typer.Context, urls: list[str], try_login: bool = True) -> bo
|
|||||||
path_base=settings.data.download_base_path,
|
path_base=settings.data.download_base_path,
|
||||||
fn_logger=fn_logger,
|
fn_logger=fn_logger,
|
||||||
progress=progress,
|
progress=progress,
|
||||||
|
progress_overall=progress_overall,
|
||||||
)
|
)
|
||||||
|
|
||||||
progress_table = Table.grid()
|
progress_table = Table.grid()
|
||||||
|
|
||||||
# Style Progress display.
|
# Style Progress display.
|
||||||
progress_table.add_row(Panel.fit(progress, title="Download Progress", border_style="green", padding=(2, 2)))
|
progress_table.add_row(progress)
|
||||||
|
progress_table.add_row(progress_overall)
|
||||||
|
|
||||||
|
progress_group = Group(
|
||||||
|
progress_table,
|
||||||
|
)
|
||||||
|
|
||||||
urls_pos_last = len(urls) - 1
|
urls_pos_last = len(urls) - 1
|
||||||
|
|
||||||
# Use a single Live display for both progress and table
|
# Use a single Live display for both progress and table
|
||||||
with Live(progress_table, refresh_per_second=20):
|
with Live(progress_group, refresh_per_second=20, vertical_overflow="visible"):
|
||||||
for item in urls:
|
try:
|
||||||
media_type: MediaType | bool = False
|
for item in urls:
|
||||||
|
media_type: MediaType | bool = False
|
||||||
|
|
||||||
# Extract media name and id from link.
|
# Extract media name and id from link.
|
||||||
if "http" in item:
|
if "http" in item:
|
||||||
media_type = get_tidal_media_type(item)
|
media_type = get_tidal_media_type(item)
|
||||||
item_id = get_tidal_media_id(item)
|
item_id = get_tidal_media_id(item)
|
||||||
file_template = get_format_template(media_type, settings)
|
file_template = get_format_template(media_type, settings)
|
||||||
else:
|
|
||||||
print(f"It seems like that you have supplied an invalid URL: {item}")
|
|
||||||
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Download media.
|
|
||||||
if media_type in [MediaType.TRACK, MediaType.VIDEO]:
|
|
||||||
download_delay: bool = bool(settings.data.download_delay and urls.index(item) < urls_pos_last)
|
|
||||||
|
|
||||||
dl.item(
|
|
||||||
media_id=item_id, media_type=media_type, file_template=file_template, download_delay=download_delay
|
|
||||||
)
|
|
||||||
elif media_type in [MediaType.ALBUM, MediaType.PLAYLIST, MediaType.MIX, MediaType.ARTIST]:
|
|
||||||
item_ids: [int] = []
|
|
||||||
|
|
||||||
if media_type == MediaType.ARTIST:
|
|
||||||
media = instantiate_media(ctx.obj[CTX_TIDAL].session, media_type, item_id)
|
|
||||||
media_type = MediaType.ALBUM
|
|
||||||
item_ids = item_ids + all_artist_album_ids(media)
|
|
||||||
else:
|
else:
|
||||||
item_ids.append(item_id)
|
print(f"It seems like that you have supplied an invalid URL: {item}")
|
||||||
|
|
||||||
for item_id in item_ids:
|
continue
|
||||||
dl.items(
|
|
||||||
|
# Download media.
|
||||||
|
if media_type in [MediaType.TRACK, MediaType.VIDEO]:
|
||||||
|
download_delay: bool = bool(settings.data.download_delay and urls.index(item) < urls_pos_last)
|
||||||
|
|
||||||
|
dl.item(
|
||||||
media_id=item_id,
|
media_id=item_id,
|
||||||
media_type=media_type,
|
media_type=media_type,
|
||||||
file_template=file_template,
|
file_template=file_template,
|
||||||
video_download=ctx.obj[CTX_TIDAL].settings.data.video_download,
|
download_delay=download_delay,
|
||||||
download_delay=settings.data.download_delay,
|
|
||||||
)
|
)
|
||||||
|
elif media_type in [MediaType.ALBUM, MediaType.PLAYLIST, MediaType.MIX, MediaType.ARTIST]:
|
||||||
|
item_ids: [int] = []
|
||||||
|
|
||||||
# Clear and stop progress display
|
if media_type == MediaType.ARTIST:
|
||||||
progress.refresh()
|
media = instantiate_media(ctx.obj[CTX_TIDAL].session, media_type, item_id)
|
||||||
progress.stop()
|
media_type = MediaType.ALBUM
|
||||||
print("\nDownload completed!")
|
item_ids = item_ids + all_artist_album_ids(media)
|
||||||
|
else:
|
||||||
|
item_ids.append(item_id)
|
||||||
|
|
||||||
|
for item_id in item_ids:
|
||||||
|
dl.items(
|
||||||
|
media_id=item_id,
|
||||||
|
media_type=media_type,
|
||||||
|
file_template=file_template,
|
||||||
|
video_download=ctx.obj[CTX_TIDAL].settings.data.video_download,
|
||||||
|
download_delay=settings.data.download_delay,
|
||||||
|
)
|
||||||
|
finally:
|
||||||
|
# Clear and stop progress display
|
||||||
|
progress.refresh()
|
||||||
|
progress.stop()
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|||||||
+10
-7
@@ -73,6 +73,7 @@ class Download:
|
|||||||
fn_logger: Callable
|
fn_logger: Callable
|
||||||
progress_gui: ProgressBars
|
progress_gui: ProgressBars
|
||||||
progress: Progress
|
progress: Progress
|
||||||
|
progress_overall: Progress
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
@@ -82,6 +83,7 @@ class Download:
|
|||||||
skip_existing: bool = False,
|
skip_existing: bool = False,
|
||||||
progress_gui: ProgressBars = None,
|
progress_gui: ProgressBars = None,
|
||||||
progress: Progress = None,
|
progress: Progress = None,
|
||||||
|
progress_overall: Progress = None,
|
||||||
):
|
):
|
||||||
self.settings = Settings()
|
self.settings = Settings()
|
||||||
self.session = session
|
self.session = session
|
||||||
@@ -89,6 +91,7 @@ class Download:
|
|||||||
self.fn_logger = fn_logger
|
self.fn_logger = fn_logger
|
||||||
self.progress_gui = progress_gui
|
self.progress_gui = progress_gui
|
||||||
self.progress = progress
|
self.progress = progress
|
||||||
|
self.progress_overall = progress_overall
|
||||||
self.path_base = path_base
|
self.path_base = path_base
|
||||||
|
|
||||||
if not self.settings.data.path_binary_ffmpeg and (
|
if not self.settings.data.path_binary_ffmpeg and (
|
||||||
@@ -150,8 +153,6 @@ class Download:
|
|||||||
total_size_in_bytes: int = int(r.headers.get("content-length", 0))
|
total_size_in_bytes: int = int(r.headers.get("content-length", 0))
|
||||||
block_size: int | None = 1048576
|
block_size: int | None = 1048576
|
||||||
progress_total: float = total_size_in_bytes / block_size
|
progress_total: float = total_size_in_bytes / block_size
|
||||||
except:
|
|
||||||
raise
|
|
||||||
finally:
|
finally:
|
||||||
r.close()
|
r.close()
|
||||||
else:
|
else:
|
||||||
@@ -709,10 +710,12 @@ class Download:
|
|||||||
progress_stdout: bool = True
|
progress_stdout: bool = True
|
||||||
else:
|
else:
|
||||||
progress_stdout: bool = False
|
progress_stdout: bool = False
|
||||||
self.progress_gui.list_name.emit(list_media_name_short[:30])
|
self.progress_gui.list_name.emit(list_media_name_short)
|
||||||
|
|
||||||
|
progress: Progress = self.progress_overall if self.progress_overall else self.progress
|
||||||
|
|
||||||
# Create the list progress task.
|
# Create the list progress task.
|
||||||
p_task1: TaskID = self.progress.add_task(
|
p_task1: TaskID = progress.add_task(
|
||||||
f"[green]List '{list_media_name_short}'", total=len(items), visible=progress_stdout
|
f"[green]List '{list_media_name_short}'", total=len(items), visible=progress_stdout
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -720,7 +723,7 @@ class Download:
|
|||||||
result_dirs: [pathlib.Path] = []
|
result_dirs: [pathlib.Path] = []
|
||||||
|
|
||||||
# Iterate through list items
|
# Iterate through list items
|
||||||
while not self.progress.finished:
|
while not progress.finished:
|
||||||
with futures.ThreadPoolExecutor(max_workers=self.settings.data.downloads_concurrent_max) as executor:
|
with futures.ThreadPoolExecutor(max_workers=self.settings.data.downloads_concurrent_max) as executor:
|
||||||
# Dispatch all download tasks to worker threads
|
# Dispatch all download tasks to worker threads
|
||||||
l_futures: [any] = [
|
l_futures: [any] = [
|
||||||
@@ -744,10 +747,10 @@ class Download:
|
|||||||
result_dirs.append(result_path_file.parent)
|
result_dirs.append(result_path_file.parent)
|
||||||
|
|
||||||
# Advance progress bar.
|
# Advance progress bar.
|
||||||
self.progress.advance(p_task1)
|
progress.advance(p_task1)
|
||||||
|
|
||||||
if not progress_stdout:
|
if not progress_stdout:
|
||||||
self.progress_gui.list_item.emit(self.progress.tasks[p_task1].percentage)
|
self.progress_gui.list_item.emit(progress.tasks[p_task1].percentage)
|
||||||
|
|
||||||
# Create playlist file
|
# Create playlist file
|
||||||
if self.settings.data.playlist_create:
|
if self.settings.data.playlist_create:
|
||||||
|
|||||||
Reference in New Issue
Block a user