def download_file(url: str, destination: Path, show_progress: bool = True) -> Path:
if destination.is_dir():
destination /= Path(urlsplit(url).path).name
import niquests
with niquests.get(url, stream=True, timeout=60) as response:
response.raise_for_status()
content_length = response.headers.get("content-length")
try:
total = int(content_length) if content_length else None
except ValueError:
total = None
file = NamedTemporaryFile(dir=destination.parent, prefix=f".{destination.name}.", delete=False)
temporary = Path(file.name)
from rich.progress import BarColumn, DownloadColumn, Progress, TextColumn, TimeRemainingColumn, TransferSpeedColumn
progress_display = (
Progress(
TextColumn("[progress.description]{task.description}"),
BarColumn(),
DownloadColumn(),
TransferSpeedColumn(),
TimeRemainingColumn(),
)
if show_progress
else nullcontext()
)
try:
with file, progress_display as progress:
task = progress.add_task(destination.name, total=total) if progress else None
for chunk in response.iter_content(chunk_size=1024 * 1024):
file.write(chunk)
if progress and task is not None:
progress.update(task, advance=len(chunk))
temporary.replace(destination)
finally:
temporary.unlink(missing_ok=True)
return destination