mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-10-20 18:59:07 -05:00
fix: draw the download bar on a terminal only
This commit is contained in:
1 parent
6b9300f601
commit
8da77961f5
2 files changed
+51
-8
No files matched your search
+17
-8
@@ -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}")
|
||||
|
||||
|
||||
@@ -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()
|
||||
Reference in new issue
Block a user