2020-03-10 22:18:23 +00:00
|
|
|
"""
|
|
|
|
A rudimentary URL downloader (like wget or curl) to demonstrate Rich progress bars.
|
|
|
|
"""
|
|
|
|
|
2020-03-07 17:45:01 +00:00
|
|
|
from concurrent.futures import ThreadPoolExecutor
|
2020-03-08 16:49:36 +00:00
|
|
|
from functools import partial
|
2020-03-07 17:45:01 +00:00
|
|
|
import os.path
|
2020-03-08 16:49:36 +00:00
|
|
|
import sys
|
|
|
|
from typing import Iterable
|
2020-03-07 17:45:01 +00:00
|
|
|
from urllib.request import urlopen
|
|
|
|
|
2020-03-10 17:12:39 +00:00
|
|
|
from rich.progress import (
|
2020-03-10 18:16:55 +00:00
|
|
|
BarColumn,
|
2020-03-22 15:46:43 +00:00
|
|
|
DownloadColumn,
|
2020-05-01 13:27:19 +00:00
|
|
|
TextColumn,
|
2020-03-10 18:16:55 +00:00
|
|
|
TransferSpeedColumn,
|
|
|
|
TimeRemainingColumn,
|
2020-03-10 17:12:39 +00:00
|
|
|
Progress,
|
|
|
|
TaskID,
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
progress = Progress(
|
2020-05-01 13:27:19 +00:00
|
|
|
TextColumn("[bold blue]{task.fields[filename]}", justify="right"),
|
2020-03-22 15:46:43 +00:00
|
|
|
BarColumn(bar_width=None),
|
2020-05-01 13:27:19 +00:00
|
|
|
"[progress.percentage]{task.percentage:>3.1f}%",
|
2020-03-10 17:12:39 +00:00
|
|
|
"•",
|
2020-03-22 15:46:43 +00:00
|
|
|
DownloadColumn(),
|
2020-03-10 17:12:39 +00:00
|
|
|
"•",
|
2020-03-10 18:16:55 +00:00
|
|
|
TransferSpeedColumn(),
|
2020-03-10 17:12:39 +00:00
|
|
|
"•",
|
2020-03-10 18:16:55 +00:00
|
|
|
TimeRemainingColumn(),
|
2020-03-10 17:12:39 +00:00
|
|
|
)
|
2020-03-07 17:45:01 +00:00
|
|
|
|
|
|
|
|
2020-03-08 16:49:36 +00:00
|
|
|
def copy_url(task_id: TaskID, url: str, path: str) -> None:
|
|
|
|
"""Copy data from a url to a local file."""
|
2020-03-07 17:45:01 +00:00
|
|
|
response = urlopen(url)
|
2020-03-10 22:18:23 +00:00
|
|
|
# This will break if the response doesn't contain content length
|
2020-03-08 16:49:36 +00:00
|
|
|
progress.update(task_id, total=int(response.info()["Content-length"]))
|
|
|
|
with open(path, "wb") as dest_file:
|
2020-05-24 10:37:00 +00:00
|
|
|
progress.start_task(task_id)
|
2020-03-08 16:49:36 +00:00
|
|
|
for data in iter(partial(response.read, 32768), b""):
|
|
|
|
dest_file.write(data)
|
|
|
|
progress.update(task_id, advance=len(data))
|
2020-03-07 17:45:01 +00:00
|
|
|
|
|
|
|
|
2020-03-08 16:49:36 +00:00
|
|
|
def download(urls: Iterable[str], dest_dir: str):
|
|
|
|
"""Download multuple files to the given directory."""
|
|
|
|
with progress:
|
|
|
|
with ThreadPoolExecutor(max_workers=4) as pool:
|
|
|
|
for url in urls:
|
|
|
|
filename = url.split("/")[-1]
|
|
|
|
dest_path = os.path.join(dest_dir, filename)
|
2020-05-24 10:37:00 +00:00
|
|
|
task_id = progress.add_task("download", filename=filename, start=False)
|
2020-03-08 16:49:36 +00:00
|
|
|
pool.submit(copy_url, task_id, url, dest_path)
|
2020-03-07 17:45:01 +00:00
|
|
|
|
|
|
|
|
2020-03-08 16:49:36 +00:00
|
|
|
if __name__ == "__main__":
|
2020-05-01 13:27:19 +00:00
|
|
|
# Try with https://releases.ubuntu.com/20.04/ubuntu-20.04-desktop-amd64.iso
|
2020-03-08 16:49:36 +00:00
|
|
|
if sys.argv[1:]:
|
|
|
|
download(sys.argv[1:], "./")
|
|
|
|
else:
|
2020-03-10 17:12:39 +00:00
|
|
|
print("Usage:\n\tpython downloader.py URL1 URL2 URL3 (etc)")
|