fix: draw the download bar on a terminal only

This commit is contained in:
Abdessamad Derraz committed 2026-10-18 16:30:04 +02:00
1 parent 6b9300f601
commit 8da77961f5
2 files changed
+51 -8

No files matched your search

+17 -8
View File
@@ -194,9 +194,13 @@ def download_file(
url, headers={"User-Agent": "retrobios-downloader/1.0"}
)
# A redrawn bar only on a terminal: written to a log, 32,768 redraws of a
# 2 GiB part made one line of nearly 3 MB.
live = sys.stdout.isatty() and os.environ.get("TERM") != "dumb"
with urllib.request.urlopen(req, timeout=300) as resp:
total = int(resp.headers.get("Content-Length", expected_size))
downloaded = 0
shown = -1
with open(dest, "wb") as f:
while True:
@@ -206,16 +210,21 @@ def download_file(
f.write(chunk)
downloaded += len(chunk)
if total > 0:
if total > 0 and live:
pct = downloaded * 100 // total
bar = "=" * (pct // 2) + " " * (50 - pct // 2)
print(
f"\r {label}[{bar}] {pct}% ({downloaded:,}/{total:,})",
end="",
flush=True,
)
if pct != shown:
shown = pct
bar = "=" * (pct // 2) + " " * (50 - pct // 2)
print(
f"\r {label}[{bar}] {pct}% ({downloaded:,}/{total:,})",
end="",
flush=True,
)
print()
if live:
print()
else:
print(f" {label}{downloaded:,} bytes")
if expected_size and downloaded != expected_size:
raise ValueError(f"downloaded {downloaded} bytes; expected {expected_size}")
+34
View File
@@ -583,5 +583,39 @@ class TestZipPartsShell(ZipPartsTests, ZipPartsCase, TestDownloadShell):
pass
class AProgressBarOnlyOnATerminal(unittest.TestCase):
"""Redirected to a log, download.py wrote a carriage-return redraw per
64 KiB block: one line of nearly 3 MB for a 2 GiB part."""
def test_a_log_gets_one_line(self):
import contextlib
import io as _io
import tempfile as _tempfile
from pathlib import Path as _Path
from unittest import mock
import download
class Body(_io.BytesIO):
headers = {"Content-Length": str(200_000)}
def __enter__(self):
return self
def __exit__(self, *exc):
return False
out = _io.StringIO()
with _tempfile.TemporaryDirectory() as directory, \
mock.patch.object(download.urllib.request, "urlopen",
lambda *a, **k: Body(b"x" * 200_000)), \
contextlib.redirect_stdout(out):
download.download_file("https://example.com/a.zip",
_Path(directory) / "a.zip", 200_000, "a.zip ")
self.assertNotIn("\r", out.getvalue())
self.assertEqual(out.getvalue().count("\n"), 1)
if __name__ == "__main__":
unittest.main()