diff --git a/CHANGELOG.md b/CHANGELOG.md index e528e41..1c3560c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [UNRELEASED] + +* Download status is now displayed while downloading Shinylive assets. ## [0.6.0] - 2024-09-03 diff --git a/shinylive/_assets.py b/shinylive/_assets.py index 3dcfcd4..a01d1d4 100644 --- a/shinylive/_assets.py +++ b/shinylive/_assets.py @@ -4,6 +4,7 @@ import re import shutil import sys +import time import urllib.request from pathlib import Path from typing import Optional @@ -16,6 +17,7 @@ def download_shinylive( destdir: str | Path | None = None, version: str = SHINYLIVE_ASSETS_VERSION, url: Optional[str] = None, + status: bool = True, ) -> None: if destdir is None: # Note that this is the cache directory, which is the parent of the assets @@ -30,7 +32,32 @@ def download_shinylive( try: print(f"Downloading {url}...", file=sys.stderr) - tmp_name, _ = urllib.request.urlretrieve(url) + + start_time = time.time() + last_update_time = start_time + + def reporthook(count: int, block_size: int, total_size: int): + if not status: + return + + nonlocal last_update_time + current_time = time.time() + + if current_time - last_update_time < 1: + return + + duration = current_time - start_time + progress_size = int(count * block_size) + speed = int(progress_size / (1024 * duration)) + percent = min(int(count * block_size * 100 / total_size), 100) + sys.stderr.write( + f"\r{percent}%, {speed} KB/s, {progress_size / (1024 * 1024):.1f}/{total_size / (1024 * 1024):.1f} MB" + ) + sys.stderr.flush() + last_update_time = current_time + + tmp_name, _ = urllib.request.urlretrieve(url, reporthook=reporthook) + sys.stderr.write("\n") print(f"Unzipping to {destdir}/", file=sys.stderr) tar_safe_extractall(tmp_name, destdir) diff --git a/shinylive/_main.py b/shinylive/_main.py index 02b3cdd..a14d4fc 100644 --- a/shinylive/_main.py +++ b/shinylive/_main.py @@ -226,14 +226,23 @@ def assets_info( default=None, help="URL to download from. If used, this will override --version.", ) +@click.option( + "--status/--no-status", + is_flag=True, + default=True, + help="Enable/disable status output during download.", +) def download( version: str, dir: Optional[str | Path], url: Optional[str], + status: bool, ) -> None: if version is None: # pyright: ignore[reportUnnecessaryComparison] version = SHINYLIVE_ASSETS_VERSION - _assets.download_shinylive(destdir=upgrade_dir(dir), version=version, url=url) + _assets.download_shinylive( + destdir=upgrade_dir(dir), version=version, url=url, status=status + ) cleanup_help = f"Remove all versions of local assets except the currently-used version, {SHINYLIVE_ASSETS_VERSION}."