Enhanced progress bars with themes, colors, and custom templates
Project description
Title: progressor-lib
Python Library Version: 1.0.1
Dependencies: Minimal, no external libraries needed. .py & .toml files.
Author: Dr. Libor Benes, M.A., Creator of progressor-lib.
This Python Library was developed on Sunday, January 11, 2026.
This README.md is created by Dr. Libor Benes, M.A., on Sunday, January 11, 2026.
This Python Library was developed by Dr. Libor Benes, M.A., using Grok 3 AI and DeepSeek AI for code generation and for this README.md file.
Support E-mail: Benes@iwp.edu
Purpose: progressor-lib is a Python library for enhanced progress bars with themes, colors, and custom templates.
Features: • 15+ Built-in Styles: Block, classic, braille, arrows, circles, squares, triangles, and more. • Full Color Support: ANSI color themes including gradients and rainbow effects. • Custom Templates: Create progress bars with any Unicode characters or emojis. • Unicode Collections: Extensive character sets from blocks, geometric symbols, and emojis. • Multi-bar Display: Track multiple concurrent processes simultaneously. • Real-time Metrics: Show percentage, counter, ETA, and speed/throughput. • Zero Dependencies: Pure Python, works anywhere Python 3.8+ runs.
Installation:
pip install progressor-lib
Quick Start:
import time
from progressor-lib import get_progress_drawer, ProgressStyle
# Create a progress drawer
draw = get_progress_drawer(
style=ProgressStyle.BLOCK,
width=40,
show_percentage=True,
show_counter=True,
color_theme="green_red"
)
# Use it in your loop
for i in range(101):
progress = i / 100.0
draw(progress, current=i*10)
time.sleep(0.05)
Examples:
Multiple Styles:
from progressor-lib import get_progress_drawer, ProgressStyle
# Block style with detailed info
draw1 = get_progress_drawer(
style=ProgressStyle.BLOCK,
width=30,
show_percentage=True,
show_counter=True,
show_eta=True,
show_speed=True
)
# Circle progression
draw2 = get_progress_drawer(
style=ProgressStyle.CIRCLE,
width=20,
color_theme="gradient"
)
# Star rating style
draw3 = get_progress_drawer(
style=ProgressStyle.STAR,
width=15,
show_percentage=True
)
Custom Characters:
from progressor-lib import get_progress_drawer
# Simple custom characters
draw = get_progress_drawer(
custom_chars=("█", "░"), # (filled, empty)
width=25,
show_percentage=True
)
# Or use Unicode block elements
from progressor-lib import UnicodeBlocks
draw = get_progress_drawer(
style=UnicodeBlocks.HORIZONTAL,
width=20,
color_theme="rainbow"
)
Multi-Bar Display:
from progressor-lib import MultiProgress
import time
# Track 3 concurrent processes
multi = MultiProgress(count=3, style="block", width=25)
# Update each progress independently
multi.update(0, 0.3, "Downloading")
multi.update(1, 0.7, "Processing")
multi.update(2, 0.5, "Compressing")
time.sleep(1)
multi.complete() # Clean up display
Available Styles:
Style Example Description
ProgressStyle.BLOCK ████████░░░░░░░░ Smooth block progression
ProgressStyle.CLASSIC ■■■■■■■■□□□□□□□□ Classic filled/empty squares
ProgressStyle.BRAILLE ⣿⣿⣿⣿⣀⣀⣀⣀ Braille pattern progression
ProgressStyle.ARROW >>>>>>>>-------- Arrow forward
ProgressStyle.VERTICAL ▁▂▃▄▅▆▇█ Vertical height increase
ProgressStyle.CIRCLE ○◔◑◕● Circle filling animation
ProgressStyle.SQUARE □◱◲■ Square filling animation
ProgressStyle.GRADIENT ░▒▓█ Shade gradient
ProgressStyle.STAR ★★★★☆☆☆☆ Star rating
ProgressStyle.TRIANGLE ▲▲▲▲▽▽▽▽ Triangle progression
ProgressStyle.BOUNCE (→ ) Bouncing animation
Plus spinner variants ⠋⠙⠹⠸⠼⠴ Various spinner styles
Color Themes:
Theme Description Best For
None No coloring (default) Simple terminals
"green_red" Green progress, red remaining Success/failure indicators
"blue_yellow" Blue progress, yellow remaining Cool/warm contrast
"gradient" Red→Yellow→Green based on progress Process completion
"rainbow" Rainbow colors across the bar Fun, colorful displays
"monochrome" Bright white on black Low-color terminals
"terminal" Default colors with dimmed empty Subtle, clean look
Unicode Collections:
The library includes organized character sets:
from progressor-lib import UnicodeBlocks, GeometricSymbols, EmojiThemes
# Block elements (8 levels of fill)
UnicodeBlocks.HORIZONTAL # ['▏', '▎', '▍', '▌', '▋', '▊', '▉', '█']
# Geometric shapes
GeometricSymbols.CIRCLES["filled"] # ['○', '◔', '◑', '◕', '●']
# Emoji themes (modern terminals)
EmojiThemes.NATURE["weather"] # ['🌧️', '🌦️', '⛅', '🌤️', '☀️']
# Create custom sequences
from progressor-lib import CustomTemplate
CustomTemplate.from_string("♩♪♫♬", stages=10)
API Reference:
get_progress_drawer()
def get_progress_drawer(
style: Union[str, List[str]] = "block",
width: int = 30,
show_percentage: bool = True,
show_counter: bool = False,
show_eta: bool = False,
show_speed: bool = False,
spinner_only: bool = False,
color_theme: Optional[Union[str, Callable]] = None,
custom_chars: Optional[Tuple[str, str]] = None
) -> Callable[[float, Optional[int], Optional[float], Optional[float]], None]
MultiProgress Class:
multi = MultiProgress(count=3, style="block", width=30)
multi.update(index, progress, label="")
multi.complete()
progressor-lib/
├── LICENSE # MIT License ✓
├── README.md # Documentation
├── CHANGELOG.md # Changes
├── pyproject.toml # Build config (version: 1.0.1)
└── src/
└── progressor-lib/
├── __init__.py # (version: 1.0.1)
├── progress.py
├── colors.py
└── themes.py
Requirements:
• Python: 3.8 or higher
• Terminal: UTF-8 support (for Unicode characters)
• Colors: ANSI color support (most modern terminals)
Testing:
# After installation
python -c "from progressor-lib import get_progress_drawer, ProgressStyle; print('Import successful')"
# Run the advanced test
python advanced_test.py
Contributing:
Contributions are welcome! Please feel free to submit a Pull Request.
License:
MIT License - see LICENSE file for details.
Files:
1) LICENSE
MIT License
Copyright (c) 2026 Dr. Libor Benes, M.A.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
--------------------------------------------------------------------------------------------------
2) README.md
This file.
--------------------------------------------------------------------------------------------------
3) CHANGELOG.md
# CHANGELOG.md
All published changes to progressor-lib to be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.1/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
[1.0.1] - 2026-01-11
Added:
• Initial public release.
• Progress bar styles: Block, classic, braille, arrow, equal, dot, vertical, circle, square, gradient, hash, star, triangle, bounce.
• Spinner animations: Simple, dots, arrow spinners.
• Color support: 7 color themes (green_red, blue_yellow, gradient, rainbow, monochrome, terminal).
• Unicode collections: Block elements, geometric symbols, emoji themes, ASCII art, fancy symbols.
• Custom templates: Create progress bars with any characters.
• Multi-bar display: Track multiple concurrent processes.
• Real-time metrics: Percentage, counter, ETA, speed/throughput.
• Zero dependencies: Pure Python, uses only standard library.
Technical:
• Full Python type hints.
• Comprehensive error handling.
• MIT License.
• Python 3.8+ compatibility.
--------------------------------------------------------------------------------------------------
4) pyproject.toml
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
name = "progressor-lib"
version = "1.0.1"
description = "Enhanced progress bars with themes, colors, and custom templates"
readme = "README.md"
requires-python = ">=3.8"
authors = [
{name = "Dr. Libor Benes, M.A.", email = "Benes@iwp.edu"}
]
license = {text = "MIT"}
classifiers = [
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Topic :: Software Development :: Libraries",
"Topic :: Software Development :: User Interfaces",
"Topic :: Terminals"
]
[project.urls]
Homepage = "https://github.com/LiborBenes-US/progressor-lib"
Repository = "https://github.com/LiborBenes-US/progressor-lib"
Issues = "https://github.com/LiborBenes-US/progressor-lib/issues"
[tool.hatch.build.targets.wheel]
packages = ["src/progressor"]
--------------------------------------------------------------------------------------------------
5) src/progressor-lib/__init__.py
"""
progressor-lib - Enhanced progress bars with themes, colors, and custom templates.
Minimal dependencies, no external libraries needed.
"""
from .progress import get_progress_drawer, ProgressStyle, MultiProgress
from .colors import Colors, ColorTheme, apply_color
from .themes import (
UnicodeBlocks, GeometricSymbols, EmojiThemes,
ASCIIArt, FancySymbols, CustomTemplate
)
__version__ = "1.0.1"
__all__ = [
"get_progress_drawer",
"ProgressStyle",
"MultiProgress",
"Colors",
"ColorTheme",
"apply_color",
"UnicodeBlocks",
"GeometricSymbols",
"EmojiThemes",
"ASCIIArt",
"FancySymbols",
"CustomTemplate",
"__version__"
]
--------------------------------------------------------------------------------------------------
6) src/progressor-lib/progress.py
"""
Main progress bar implementation.
Enhanced with themes, colors, and custom templates.
Minimal dependencies, no external libraries needed.
"""
import sys
import time
from typing import Callable, Optional, Union, List, Tuple
# Import new modules
from .colors import ColorTheme
from .themes import UnicodeBlocks, GeometricSymbols
class ProgressStyle:
"""Predefined progress bar styles (expanded)"""
# Block styles
BLOCK = "block" # ████████░░░░░░░░
CLASSIC = "classic" # [■■■■■■■■□□□□□□□□]
BRAILLE = "braille" # ⣿⣿⣿⣿⣀⣀⣀⣀
ARROW = "arrow" # >>>>>>>>--------
EQUAL = "equal" # =========-------
DOT = "dot" # ••••••••........
# Spinners
SPIN_SIMPLE = "spin_simple" # |/-\\|/-\...
SPIN_DOTS = "spin_dots" # ⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏
SPIN_ARROW = "spin_arrow" # ←↖↑↗→↘↓↙
# New styles
VERTICAL = "vertical" # ▁▂▃▄▅▆▇█ (vertical blocks)
CIRCLE = "circle" # ○◔◑◕●
SQUARE = "square" # □◱◲■
GRADIENT = "gradient" # ░▒▓█ (shaded gradient)
HASH = "hash" # #####.....
STAR = "star" # ★★★★★☆☆☆☆☆
TRIANGLE = "triangle" # ▲▲▲▲▽▽▽▽
BOUNCE = "bounce" # (→ ) ( → ) etc.
def get_progress_drawer(
style: Union[str, List[str]] = "block",
width: int = 30,
show_percentage: bool = True,
show_counter: bool = False,
show_eta: bool = False,
show_speed: bool = False, # NEW: Show operations per second
spinner_only: bool = False,
color_theme: Optional[Union[str, Callable]] = None,
custom_chars: Optional[Tuple[str, str]] = None
) -> Callable[[float, Optional[int], Optional[float], Optional[float]], None]:
"""
Factory that returns a progress drawing function with selected style.
Enhanced with color support and custom character sets.
The returned function signature:
def draw(progress: float, current: int | None = None,
eta: float | None = None, speed: float | None = None) -> None:
# progress ∈ [0,1]
# speed: operations per second (if show_speed=True)
"""
# Track start time for speed calculation
start_time = time.time()
last_update = start_time
last_value = 0
# Determine style and handle custom inputs
style_name = ""
filled_char = ""
empty_char = ""
chars = []
if custom_chars is not None:
# User provided custom characters like ("@", ".")
filled_char, empty_char = custom_chars
style_name = "custom"
elif isinstance(style, list):
# User provided a list of characters for progressive fill
chars = style
if len(chars) < 1:
raise ValueError("Character list must have at least one character")
style_name = "custom_list"
else:
# Regular style name
style_name = style.lower()
# Map style names to drawing functions
if style_name == "block":
chars = " ▏▎▍▋▊▉"
def draw_func(p: float):
filled = int(p * (width * len(chars)-1))
full = filled // (len(chars)-1)
part = filled % (len(chars)-1)
bar = chars[-1] * full + (chars[part] if part else "")
bar += " " * (width - len(bar))
return bar, " " * width
elif style_name == "classic":
def draw_func(p: float):
filled = int(p * width)
return "■" * filled, "□" * (width - filled)
elif style_name == "braille":
braille = " ⡀⡄⡆⡇⡏⡟⡿⣿"
def draw_func(p: float):
filled = int(p * width * 4)
full = filled // 4
part = filled % 4
bar = braille[7] * full + (braille[part] if part else "")
bar += " " * (width - len(bar))
return bar, " " * width
elif style_name == "arrow":
def draw_func(p: float):
filled = int(p * width)
return ">" * filled, "-" * (width - filled)
elif style_name == "equal":
def draw_func(p: float):
filled = int(p * width)
return "=" * filled, "-" * (width - filled)
elif style_name == "dot":
def draw_func(p: float):
filled = int(p * width)
return "•" * filled, "." * (width - filled)
elif style_name == "vertical":
vertical_chars = UnicodeBlocks.VERTICAL
def draw_func(p: float):
filled = int(p * width)
bar = ""
for i in range(width):
if i < filled:
# Use different heights based on position
height_idx = min(int(p * len(vertical_chars)), len(vertical_chars)-1)
bar += vertical_chars[height_idx]
else:
bar += " "
return bar, " " * width
elif style_name == "circle":
circle_chars = GeometricSymbols.CIRCLES["filled"]
def draw_func(p: float):
filled = int(p * width)
filled_part = ""
for i in range(filled):
# Progressively fill circles
idx = min(int(p * len(circle_chars)), len(circle_chars)-1)
filled_part += circle_chars[idx]
empty_part = circle_chars[0] * (width - filled)
return filled_part, empty_part
elif style_name == "square":
square_chars = GeometricSymbols.SQUARES
def draw_func(p: float):
filled = int(p * width)
filled_part = ""
for i in range(filled):
# Progressively fill squares
idx = min(int(p * len(square_chars)), len(square_chars)-1)
filled_part += square_chars[idx]
empty_part = square_chars[0] * (width - filled)
return filled_part, empty_part
elif style_name == "gradient":
def draw_func(p: float):
filled = int(p * width)
bar = ""
for i in range(width):
if i < filled:
# More filled = darker shade
if p < 0.33:
bar += "░"
elif p < 0.66:
bar += "▒"
else:
bar += "▓"
else:
bar += " "
return bar, " " * width
elif style_name == "hash":
def draw_func(p: float):
filled = int(p * width)
return "#" * filled, "." * (width - filled)
elif style_name == "star":
def draw_func(p: float):
filled = int(p * width)
return "★" * filled, "☆" * (width - filled)
elif style_name == "triangle":
def draw_func(p: float):
filled = int(p * width)
return "▲" * filled, "▽" * (width - filled)
elif style_name == "bounce":
frames = ["(→ )", "( → )", "( → )", "( → )", "( →)",
"( ← )", "( ← )", "( ← )", "(← )"]
def make_bounce():
i = 0
def bounce(p: float):
nonlocal i
# Scale frame based on progress
frame_idx = int(p * (len(frames) - 1))
s = frames[frame_idx]
i = (i + 1) % len(frames)
return s, ""
return bounce
draw_func = make_bounce()
elif style_name == "spin_arrow":
frames = ["←", "↖", "↑", "↗", "→", "↘", "↓", "↙"]
def make_spinner():
i = 0
def spin(_: float):
nonlocal i
s = frames[i % len(frames)]
i = (i + 1) % len(frames)
return s * (width // 3) if spinner_only else s, ""
return spin
draw_func = make_spinner()
elif style_name in ("spin_simple", "spin_dots"):
if style_name == "spin_simple":
frames = r"\|/-"
else:
frames = "⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏"
def make_spinner():
i = 0
def spin(_: float):
nonlocal i
s = frames[i % len(frames)]
i = (i + 1) % len(frames)
return s * (width // 3) if spinner_only else s, ""
return spin
draw_func = make_spinner()
elif style_name == "custom":
# Custom characters from user (filled_char, empty_char)
def draw_func(p: float):
filled = int(p * width)
return filled_char * filled, empty_char * (width - filled)
elif style_name == "custom_list":
# List of characters for progressive fill
if len(chars) == 0:
raise ValueError("Character list cannot be empty")
def draw_func(p: float):
filled = int(p * width)
filled_part = ""
for i in range(filled):
# Use character based on position in sequence
idx = min(int(p * len(chars)), len(chars)-1)
filled_part += chars[idx]
empty_part = chars[0] * (width - filled)
return filled_part, empty_part
else:
raise ValueError(f"Unknown style: {style!r}. Available: {', '.join([k for k in ProgressStyle.__dict__.keys() if not k.startswith('_')])}")
# Color theme handler
if color_theme is None:
color_handler = ColorTheme.default
elif callable(color_theme):
color_handler = color_theme
elif color_theme == "green_red":
color_handler = ColorTheme.green_red
elif color_theme == "blue_yellow":
color_handler = ColorTheme.blue_yellow
elif color_theme == "gradient":
color_handler = ColorTheme.gradient
elif color_theme == "rainbow":
color_handler = ColorTheme.rainbow
elif color_theme == "monochrome":
color_handler = ColorTheme.monochrome
elif color_theme == "terminal":
color_handler = ColorTheme.terminal
else:
color_handler = ColorTheme.default
def draw(
progress: float,
current: Optional[int] = None,
eta: Optional[float] = None,
speed: Optional[float] = None
):
"""
Draw progress bar according to selected style
Args:
progress: 0..1
current: Current item count (if show_counter=True)
eta: Estimated time remaining in seconds (if show_eta=True)
speed: Operations per second (if show_speed=True)
"""
# Fix variable scope issue
nonlocal last_update, last_value
if not 0 <= progress <= 1:
progress = max(0, min(1, progress))
# Calculate speed if not provided but requested
computed_speed = None
if show_speed and speed is None and current is not None:
now = time.time()
if now > last_update:
computed_speed = (current - last_value) / (now - last_update)
last_update = now
last_value = current
# Draw the bar
filled_part, empty_part = draw_func(progress)
# Apply color theme
if color_handler:
filled_part, empty_part = color_handler(filled_part, empty_part, progress)
bar = filled_part + empty_part
# Build info parts
parts = []
if show_percentage:
parts.append(f"{progress:5.1%}")
if show_counter and current is not None:
parts.append(f"{current:,}")
if show_eta and eta is not None and eta > 0:
if eta < 60:
parts.append(f"ETA {eta:.1f}s")
elif eta < 3600:
parts.append(f"ETA {eta/60:.1f}m")
else:
parts.append(f"ETA {eta/3600:.1f}h")
if show_speed:
speed_to_show = speed if speed is not None else computed_speed
if speed_to_show is not None:
if speed_to_show < 1000:
parts.append(f"{speed_to_show:.1f}/s")
elif speed_to_show < 1_000_000:
parts.append(f"{speed_to_show/1000:.1f}K/s")
else:
parts.append(f"{speed_to_show/1_000_000:.1f}M/s")
extra = " │ " + " ".join(parts) if parts else ""
line = f"\r{bar}{extra}"
sys.stdout.write(line)
sys.stdout.flush()
# Print newline when complete
if progress >= 1:
sys.stdout.write("\n")
sys.stdout.flush()
return draw
# Multi-bar display (simple implementation)
class MultiProgress:
"""
Simple multi-progress bar display.
Useful for tracking multiple concurrent processes.
"""
def __init__(self, count: int, style: str = "block", width: int = 30):
self.count = count
self.drawers = [get_progress_drawer(style, width, show_percentage=False)
for _ in range(count)]
self.lines_written = 0
def update(self, index: int, progress: float, label: str = ""):
"""Update a specific progress bar"""
if index < 0 or index >= self.count:
raise IndexError(f"Index {index} out of range (0-{self.count-1})")
# Move cursor to the right line
if self.lines_written:
sys.stdout.write(f"\033[{self.lines_written}A") # Move up
# Update all bars
for i in range(self.count):
if i == index:
prefix = f"{label}: " if label else f"Bar {i+1}: "
sys.stdout.write(prefix)
self.drawers[i](progress)
sys.stdout.write("\n")
else:
# Just keep existing line
sys.stdout.write("\n")
self.lines_written = self.count
sys.stdout.flush()
def complete(self):
"""Complete all progress bars"""
sys.stdout.write("\n" * self.lines_written)
sys.stdout.flush()
--------------------------------------------------------------------------------------------------
7) src/progressor-lib/colors.py
"""
ANSI color support for progress bars.
Works on most modern terminals (Linux, macOS, Windows 10+ with ANSI support).
"""
class Colors:
"""ANSI color codes for terminal output"""
# Basic colors
BLACK = "\033[30m"
RED = "\033[31m"
GREEN = "\033[32m"
YELLOW = "\033[33m"
BLUE = "\033[34m"
MAGENTA = "\033[35m"
CYAN = "\033[36m"
WHITE = "\033[37m"
# Bright colors
BRIGHT_BLACK = "\033[90m"
BRIGHT_RED = "\033[91m"
BRIGHT_GREEN = "\033[92m"
BRIGHT_YELLOW = "\033[93m"
BRIGHT_BLUE = "\033[94m"
BRIGHT_MAGENTA = "\033[95m"
BRIGHT_CYAN = "\033[96m"
BRIGHT_WHITE = "\033[97m"
# Background colors
BG_BLACK = "\033[40m"
BG_RED = "\033[41m"
BG_GREEN = "\033[42m"
BG_YELLOW = "\033[43m"
BG_BLUE = "\033[44m"
BG_MAGENTA = "\033[45m"
BG_CYAN = "\033[46m"
BG_WHITE = "\033[47m"
# Bright background colors
BG_BRIGHT_BLACK = "\033[100m"
BG_BRIGHT_RED = "\033[101m"
BG_BRIGHT_GREEN = "\033[102m"
BG_BRIGHT_YELLOW = "\033[103m"
BG_BRIGHT_BLUE = "\033[104m"
BG_BRIGHT_MAGENTA = "\033[105m"
BG_BRIGHT_CYAN = "\033[106m"
BG_BRIGHT_WHITE = "\033[107m"
# Styles
BOLD = "\033[1m"
DIM = "\033[2m"
ITALIC = "\033[3m"
UNDERLINE = "\033[4m"
BLINK = "\033[5m"
REVERSE = "\033[7m"
HIDDEN = "\033[8m"
# Reset
RESET = "\033[0m"
# Color gradients (for smooth transitions)
GRADIENT_RED_YELLOW = ["\033[38;5;196m", "\033[38;5;202m", "\033[38;5;208m",
"\033[38;5;214m", "\033[38;5;220m"]
GRADIENT_BLUE_CYAN = ["\033[38;5;21m", "\033[38;5;27m", "\033[38;5;33m",
"\033[38;5;39m", "\033[38;5;45m", "\033[38;5;51m"]
GRADIENT_GREEN = ["\033[38;5;22m", "\033[38;5;28m", "\033[38;5;34m",
"\033[38;5;40m", "\033[38;5;46m", "\033[38;5;82m"]
@staticmethod
def rgb(r: int, g: int, b: int) -> str:
"""Create 24-bit RGB color (if terminal supports it)"""
return f"\033[38;2;{r};{g};{b}m"
@staticmethod
def bg_rgb(r: int, g: int, b: int) -> str:
"""Create 24-bit background RGB color"""
return f"\033[48;2;{r};{g};{b}m"
class ColorTheme:
"""Predefined color themes for progress bars"""
@staticmethod
def default(filled: str, empty: str, progress: float = 0) -> tuple[str, str]:
"""No coloring"""
return filled, empty
@staticmethod
def green_red(filled: str, empty: str, progress: float = 0) -> tuple[str, str]:
"""Green progress, red remaining"""
return f"{Colors.GREEN}{filled}{Colors.RESET}", f"{Colors.RED}{empty}{Colors.RESET}"
@staticmethod
def blue_yellow(filled: str, empty: str, progress: float = 0) -> tuple[str, str]:
"""Blue progress, yellow remaining"""
return f"{Colors.BLUE}{filled}{Colors.RESET}", f"{Colors.YELLOW}{empty}{Colors.RESET}"
@staticmethod
def gradient(filled: str, empty: str, progress: float) -> tuple[str, str]:
"""Gradient from red to green based on position"""
if progress < 0.33:
color = Colors.RED
elif progress < 0.66:
color = Colors.YELLOW
else:
color = Colors.GREEN
return f"{color}{filled}{Colors.RESET}", f"{Colors.DIM}{empty}{Colors.RESET}"
@staticmethod
def rainbow(filled: str, empty: str, progress: float) -> tuple[str, str]:
"""Rainbow gradient across the bar"""
colors = [Colors.RED, Colors.YELLOW, Colors.GREEN,
Colors.CYAN, Colors.BLUE, Colors.MAGENTA]
idx = int(progress * (len(colors) - 1))
return f"{colors[idx]}{filled}{Colors.RESET}", empty
@staticmethod
def monochrome(filled: str, empty: str, progress: float = 0) -> tuple[str, str]:
"""Simple white on black"""
return f"{Colors.BRIGHT_WHITE}{filled}{Colors.RESET}", empty
@staticmethod
def terminal(filled: str, empty: str, progress: float = 0) -> tuple[str, str]:
"""Use terminal's default colors (dim empty part)"""
return filled, f"{Colors.DIM}{empty}{Colors.RESET}"
def apply_color(text: str, color_code: str, reset: bool = True) -> str:
"""Apply color to text"""
return f"{color_code}{text}{Colors.RESET if reset else ''}"
--------------------------------------------------------------------------------------------------
8) src/progressor-lib/themes.py
"""
Expanded collection of Unicode characters and patterns for progress bars.
Organized by category for easy discovery and use.
"""
class UnicodeBlocks:
"""Block elements from Unicode with varying fill levels"""
# Full block elements
FULL = {
"standard": "█",
"light": "▓",
"medium": "▒",
"light_shade": "░",
"dark_shade": "█",
"seven_eighths": "▉",
"three_quarters": "▊",
"five_eighths": "▋",
"half": "▌",
"three_eighths": "▍",
"quarter": "▎",
"one_eighth": "▏",
}
# Vertical blocks (for vertical progress)
VERTICAL = ["▁", "▂", "▃", "▄", "▅", "▆", "▇", "█"]
# Horizontal blocks
HORIZONTAL = ["▏", "▎", "▍", "▌", "▋", "▊", "▉", "█"]
# Braille patterns (8-dot)
BRAILLE = {
"full": "⣿",
"stages": [" ", "⡀", "⡄", "⡆", "⡇", "⡏", "⡟", "⡿", "⣿"],
"dots": ["⠀", "⠁", "⠃", "⠇", "⡇", "⡏", "⡟", "⡿", "⣿"]
}
# Box drawing elements
BOXES = {
"solid": "█",
"double": "═",
"rounded": "●",
"square": "■",
"diamond": "◆",
"triangle": "▲"
}
class GeometricSymbols:
"""Geometric shapes and symbols"""
CIRCLES = {
"filled": ["○", "◔", "◑", "◕", "●"],
"outlined": ["○", "◑", "●"],
"concentric": ["◎", "◉", "●"],
"dot_centered": ["◌", "◍", "◎"]
}
SQUARES = ["□", "◱", "◲", "■"]
TRIANGLES = {
"up": ["△", "▲"],
"down": ["▽", "▼"],
"right": ["▷", "▶"],
"left": ["◁", "◀"]
}
STARS = ["☆", "★", "✪", "✯", "✦", "✧", "✩", "✰"]
ARROWS = {
"forward": [">", "»", "›", "➔", "➙", "➛", "➜"],
"backward": ["<", "«", "‹", "➔", "➙", "➛", "➜"][::-1],
"bouncing": ["(→ )", "( → )", "( → )", "( → )", "( →)",
"( ← )", "( ← )", "( ← )", "(← )"]
}
class EmojiThemes:
"""Emoji-based progress indicators (for modern terminals)"""
TECH = {
"computers": ["🖥️", "💻", "📱", "⌚", "🎮"],
"loading": ["⏳", "⌛", "⏰", "🕐", "🕑", "🕒", "🕓", "🕔"],
"network": ["📡", "📶", "🌐", "🛰️", "📶"],
"battery": ["🔋", "🪫", "🔌", "⚡", "💡"]
}
NATURE = {
"weather": ["🌧️", "🌦️", "⛅", "🌤️", "☀️"],
"growth": ["🌱", "🌿", "🍃", "🌳", "🎄"],
"water": ["💧", "🌊", "🌨️", "❄️", "☃️"],
"day_night": ["🌑", "🌒", "🌓", "🌔", "🌕"]
}
CONSTRUCTION = {
"build": ["🚧", "👷", "🔨", "🏗️", "🏢"],
"tools": ["🛠️", "⚒️", "🔧", "🔩", "⛏️"]
}
FOOD = {
"cooking": ["🥚", "🍳", "🥓", "🍖", "🍗"],
"baking": ["🌾", "🍞", "🥖", "🥨", "🥐"],
"drinks": ["☕", "🍵", "🥤", "🍹", "🍷"]
}
class ASCIIArt:
"""Classic ASCII art patterns"""
SIMPLE = {
"equals": ["=", "-"],
"hash": ["#", "."],
"asterisk": ["*", " "],
"plus": ["+", "-"],
"at": ["@", "."]
}
RETRO = {
"pong": ["( ● )", "( ● )", "( ● )", "( ● )", "( ●)",
"( ● )", "( ● )", "( ● )", "( ● )"],
"pacman": ["C", "c", "ᴐ", "o", "O"],
"space_invaders": ["👾", "💀", "🤖", "👽", "🛸"]
}
class FancySymbols:
"""Miscellaneous fancy Unicode symbols"""
MUSICAL = ["♩", "♪", "♫", "♬", "♭", "♯", "🎵", "🎶"]
CHESS = ["♔", "♕", "♖", "♗", "♘", "♙", "♚", "♛"]
CURRENCY = ["$", "€", "£", "¥", "₿", "💎", "💵", "💰"]
ZODIAC = ["♈", "♉", "♊", "♋", "♌", "♍", "♎", "♏", "♐", "♑", "♒", "♓"]
PLANETS = ["☉", "☿", "♀", "♁", "♂", "♃", "♄", "♅", "♆", "♇"]
class CustomTemplate:
"""Utilities for creating custom progress bar templates"""
@staticmethod
def from_string(chars: str, stages: int = 8) -> list[str]:
"""
Create a progress sequence from a string of characters.
Args:
chars: String where each character is a fill level
stages: How many discrete stages to create
Returns:
List of characters for each stage
"""
if len(chars) < 2:
raise ValueError("Need at least 2 characters for filled/empty")
if stages <= len(chars):
return list(chars[:stages])
# Interpolate if we need more stages than characters
result = []
for i in range(stages):
idx = int(i * (len(chars) - 1) / (stages - 1))
result.append(chars[idx])
return result # FIXED: Actually return the result!
@staticmethod
def gradient(filled_char: str, empty_char: str, steps: int = 10) -> list[str]:
"""
Create a gradient from empty to filled character.
Args:
filled_char: Character for 100% filled
empty_char: Character for 0% filled
steps: Number of gradient steps
Returns:
List of gradient characters
"""
result = [empty_char]
for i in range(1, steps - 1):
# Mix characters for gradient effect
if i < steps // 2:
result.append(empty_char)
else:
result.append(filled_char)
result.append(filled_char)
return result
@staticmethod
def pattern(pattern: str, width: int = 30) -> str:
"""
Create a repeating pattern progress bar.
Args:
pattern: Pattern string (e.g., "=-", "◐◑", "⠋⠙")
width: Width of the progress bar
Returns:
Pattern repeated to fit width
"""
repeats = (width // len(pattern)) + 1
return (pattern * repeats)[:width]
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file progressor_lib-1.0.1.tar.gz.
File metadata
- Download URL: progressor_lib-1.0.1.tar.gz
- Upload date:
- Size: 27.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
89a6a49eda02f06882b824e813056d3e755ae5c84235522b573a9f2421fdc4cd
|
|
| MD5 |
bea5d92784af70fea833d9e7dc3c0b13
|
|
| BLAKE2b-256 |
7b9bc850cfe39aec16312c9347b84034471112b25da15430dbc3891a98531e50
|
File details
Details for the file progressor_lib-1.0.1-py3-none-any.whl.
File metadata
- Download URL: progressor_lib-1.0.1-py3-none-any.whl
- Upload date:
- Size: 20.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b320843fe1535edde969986bbfce8d5adfa3c473a1ae1e63bff349bc124f665b
|
|
| MD5 |
2d4e2bec08e6478e4d5a43ee0d4c1a52
|
|
| BLAKE2b-256 |
129d7be9f70c0ef9e049f8afce00d9fbd8d6fb14dc6366574234fb09ee498d25
|