From 9f7108d22a2e8ca1cca9667624ca3d8eceb0803a Mon Sep 17 00:00:00 2001 From: Alexander Wainwright Date: Sat, 31 Jan 2026 10:59:56 +1000 Subject: [PATCH] Add progress bar test tool --- demo_progress.py | 100 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100755 demo_progress.py diff --git a/demo_progress.py b/demo_progress.py new file mode 100755 index 0000000..1b38dbb --- /dev/null +++ b/demo_progress.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python3 +import time +import logging +import argparse +import random +from dataclasses import dataclass +from emulsion.tui import DashboardUI + +@dataclass +class MockTask: + original_file: str + timestamp: str = "2024-01-01 12:00:00" + +class MockRunner: + def __init__(self, total_items: int, rate_per_sec: float, fail_rate: float = 0.01): + self.total_items = total_items + self.rate_per_sec = rate_per_sec + self.fail_rate = fail_rate + + # Generate mock tasks + self.tasks = [ + MockTask(original_file=f"DSC_{i:05d}.JPG") + for i in range(total_items) + ] + + self.pending_tasks = list(self.tasks) + self.completed_tasks = [] # (Task, success, msg) + self.dry_run = False + + self._start_time = None + self._items_processed = 0 + + def start(self): + self._start_time = time.time() + + def update(self): + if not self._start_time: + return [] + + elapsed = time.time() - self._start_time + target_processed = int(elapsed * self.rate_per_sec) + + # Clamp to total + target_processed = min(target_processed, self.total_items) + + newly_completed = [] + + while self._items_processed < target_processed: + if not self.pending_tasks: + break + + task = self.pending_tasks.pop(0) + + # Simulate success/failure + is_success = random.random() > self.fail_rate + msg = "Updated timestamp" if is_success else "Permission denied" + + result = (task, is_success, msg) + self.completed_tasks.append(result) + newly_completed.append(result) + + self._items_processed += 1 + + return newly_completed + + def is_done(self): + return self._items_processed >= self.total_items + + @property + def progress(self): + return self._items_processed, self.total_items + +def main(): + parser = argparse.ArgumentParser(description="Demo the Emulsion Progress Bar") + parser.add_argument("-n", "--count", type=int, default=1000, help="Number of items to process") + parser.add_argument("-r", "--rate", type=float, default=50.0, help="Items per second") + parser.add_argument("-f", "--fail", type=float, default=0.005, help="Failure rate (0.0 to 1.0)") + + args = parser.parse_args() + + logging.basicConfig( + filename='emulsion.log', + level=logging.DEBUG, + format='%(asctime)s - %(levelname)s - %(message)s' + ) + logging.info('Emulsion started') + + print(f"Starting demo with {args.count} items at {args.rate}/sec...") + time.sleep(1) + + runner = MockRunner(args.count, args.rate, args.fail) + ui = DashboardUI(runner) + + try: + ui.run() + except KeyboardInterrupt: + print("\nAborted by user.") + +if __name__ == "__main__": + main()