Source code for core_mixins.cli.progress_tracker

# -*- coding: utf-8 -*-

"""
A lightweight terminal progress bar utility for CLI pipelines, with
no external dependencies, pure stdlib.
"""

import logging
import sys
import typing

GREEN  = "\033[32m"
YELLOW = "\033[33m"
CYAN   = "\033[36m"
DIM    = "\033[2m"
BOLD   = "\033[1m"
RESET  = "\033[0m"

BAR_WIDTH = 40


[docs] class ProgressTracker: """Progress tracker utility for CLI pipelines."""
[docs] def __init__( self, logger: typing.Optional[logging.Logger] = None, ) -> None: self._tty = sys.stdout.isatty() self.logger = logger
@staticmethod def _build_bar(pct: float) -> str: filled = int(pct / 100 * BAR_WIDTH) return "█" * filled + "░" * (BAR_WIDTH - filled)
[docs] def progress(self, desc: str, pct: float, note: str = "") -> None: """Overwrite the current terminal line.""" if not self._tty: return filled = self._build_bar(pct) right = f" {note}" if note else "" line = ( f" {CYAN}{RESET} {desc:<26} [{CYAN}{filled}{RESET}]" f" {pct:>5.1f}%{DIM}{right}{RESET}" ) sys.stdout.write(f"\r{line:<120}") sys.stdout.flush()
[docs] def done(self, desc: str, note: str = "") -> None: """Clear the progress line and print a persistent ✔ line.""" if self._tty: right = f" {DIM}{note}{RESET}" if note else "" line = ( f" {GREEN}{RESET} {desc:<26} [{GREEN}{'█' * BAR_WIDTH}{RESET}]" f" {100.0:>5.1f}%{DIM}{right}{RESET}" ) sys.stdout.write(f"\r{line:<120}\n") sys.stdout.flush() elif self.logger: right = f" {note}" if note else "" self.logger.info(f"✔ {desc}{right}")