From 2bb4dc9187e197262aaf9834945fadcdb2010ee2 Mon Sep 17 00:00:00 2001 From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com> Date: Tue, 20 Oct 2026 04:43:12 +0200 Subject: [PATCH] fix: the download bar fits the terminal A 2 GB part drew a 98-column line, and on an 80-column console every redraw wrapped and left a copy behind. The bar now shrinks to the width and goes below ten columns of room. --- scripts/download.py | 22 ++++++++++++++++------ tests/test_download.py | 15 +++++++++++++++ 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/scripts/download.py b/scripts/download.py index 8129cd79..f1f9c853 100644 --- a/scripts/download.py +++ b/scripts/download.py @@ -214,12 +214,9 @@ def download_file( pct = downloaded * 100 // total if pct != shown: shown = pct - bar = "=" * (pct // 2) + " " * (50 - pct // 2) - print( - f"\r {label}[{bar}] {pct}% ({downloaded:,}/{total:,})", - end="", - flush=True, - ) + columns = shutil.get_terminal_size((80, 24)).columns + line = _progress_line(label, downloaded, total, columns) + print(f"\r\033[K{line}", end="", flush=True) if live: print() @@ -229,6 +226,19 @@ def download_file( raise ValueError(f"downloaded {downloaded} bytes, expected {expected_size}") +def _progress_line(label: str, done: int, total: int, columns: int) -> str: + """One physical line shorter than the terminal: a wrapped line leaves a + copy of itself on every redraw, since \\r goes back one row only. The + bar shrinks first, then goes.""" + pct = done * 100 // total + figures = f" {pct}% ({done / 1e6:,.0f}/{total / 1e6:,.0f} MB)" + room = min(50, columns - 1 - len(f" {label}[]") - len(figures)) + if room < 10: + return f" {label}{figures.strip()}"[: columns - 1] + filled = room * pct // 100 + return f" {label}[{'=' * filled}{' ' * (room - filled)}]{figures}" + + def join_volumes(parts: list[Path], dest: Path) -> None: """Concatenate split volumes into one archive, streaming.""" with open(dest, "wb") as out: diff --git a/tests/test_download.py b/tests/test_download.py index dfd8da08..aa0ff85f 100644 --- a/tests/test_download.py +++ b/tests/test_download.py @@ -252,6 +252,21 @@ class TestJoinVolumes(unittest.TestCase): self.assertEqual(zf.testzip(), None) +class TestProgressLineWidth(unittest.TestCase): + """The bar was 98 columns for a 2 GB part: on an 80-column console each + redraw wrapped and left a line behind.""" + + def test_the_line_fits_every_width(self): + from download import _progress_line + + for columns in (20, 40, 80, 120, 200): + for done in (0, 1_000_000_000, 2_000_000_000): + with self.subTest(columns=columns, done=done): + line = _progress_line("part 1/2 ", done, 2_000_000_000, columns) + self.assertLess(len(line), columns) + self.assertIn("%", line) + + class TestStagingIsolation(unittest.TestCase): """Two downloads into one BIOS folder must not share a staging directory."""