Skip to main content

A highly configurable progress indicator library for Python with Rich and Textual support

Project description

ThothSpinner

PyPI version Python 3.11+ Rich Coverage Documentation License: MIT

A highly configurable progress indicator library for Python, built on Rich. ThothSpinner provides beautiful, composable terminal UI components including spinners, progress bars, timers, and animated messages with shimmer effects.

Demo

ThothSpinner demo

โœจ Features

  • ๐ŸŽจ Modular Components: Mix and match spinner, progress, timer, message, and hint components
  • ๐Ÿ”„ State Management: Built-in success/error states with automatic transitions
  • โœจ Shimmer Effects: Eye-catching animation effects for messages
  • ๐ŸŽฏ Thread-Safe: Proper locking for concurrent operations
  • ๐Ÿš€ Performance Optimized: Efficient rendering with minimal CPU usage
  • ๐ŸŽญ Rich Integration: Seamless integration with Rich Console and Live displays
  • ๐Ÿ“บ Textual Support: Native Textual widgets with reactive state management

๐Ÿ“š Documentation

๐Ÿš€ Quick Start

Setup

# Install from PyPI
pip install thothspinner
# or with uv (recommended)
uv add thothspinner

Explore Spinner Styles

ThothSpinner Style Browser

# Preview all 48 spinner styles in the terminal
thothspinner preview

# Preview a specific style
thothspinner preview npm_dots

# Open interactive TUI style browser
thothspinner browse

Basic Usage

from thothspinner import ThothSpinner
from rich.console import Console
from rich.live import Live
import time

console = Console()

# Simple usage with all components
with Live(ThothSpinner(), console=console) as live:
    spinner = live.renderable
    spinner.start()

    # Simulate work with progress
    for i in range(100):
        spinner.update_progress(current=i, total=100)
        time.sleep(0.05)

    spinner.success("Task completed!")

Textual Quick Start

from textual.app import App, ComposeResult
from thothspinner.textual import TextualThothSpinner
import asyncio

class MyApp(App):
    def compose(self) -> ComposeResult:
        yield TextualThothSpinner(
            spinner_style="npm_dots",
            message_text="Processing data",
            message_shimmer=True,
        )

    async def on_mount(self) -> None:
        spinner = self.query_one(TextualThothSpinner)
        spinner.start()
        await asyncio.sleep(2)
        spinner.success("Done!")

MyApp().run()

Run the Examples

# Run all examples (Rich + Textual)
just examples

# Or run by category
just examples-thothspinner    # Rich ThothSpinner examples
just examples-textual         # Textual widget examples

# Or run individual examples
just example-thothspinner-basic
just example-thothspinner-full
just example-progress
just example-timer
just example-message
just example-message-shimmer

๐Ÿ“ฆ Installation

Prerequisites

  • Python 3.11+
  • uv package manager (recommended)
  • just command runner (optional)

Install from Source

# Clone the repository
git clone https://github.com/smorin/thothspinner.git
cd thothspinner

# Install with uv (recommended)
uv sync

# Or with pip
pip install -e .

Install from PyPI

pip install thothspinner

# Or with uv (recommended)
uv add thothspinner

๐ŸŽฏ Available Components

Core Components

  • SpinnerComponent: Animated spinners with multiple styles (npm_dots, claude_stars, etc.)
  • ProgressComponent: Progress counters with various formats (percentage, fraction, etc.)
  • TimerComponent: Elapsed time display with flexible formatting
  • MessageComponent: Rotating action words with shimmer effects
  • HintComponent: Static hint text for instructions
  • ThothSpinner: Orchestrator that combines all components

Example Usage

from thothspinner import ThothSpinner
from thothspinner.rich.components import SpinnerComponent, ProgressComponent

# Individual components
spinner = SpinnerComponent(style="claude_stars", color="#FFA500")
progress = ProgressComponent(format={"style": "percentage"}, color="#00FF00")

# Or use the orchestrator for everything
spinner = ThothSpinner(
    spinner_style="npm_dots",
    message_text="Processing data",  # initial rotating message text
    message_shimmer=True,
    progress_format="percentage",
    timer_format="auto",
    hint_text="(esc to cancel)"
)

set_message() updates the current rotating message text. Use set_message_pinned() only when you explicitly want a non-rotating message.

Configuration

ThothSpinner supports both kwargs and dictionary configuration:

# Using kwargs
spinner = ThothSpinner(
    spinner_style="claude_stars",
    message_shimmer=True,
    success_duration=2.0  # Auto-clear after 2 seconds
)

# Using configuration dictionary
config = {
    "defaults": {"color": "#D97706"},
    "elements": {
        "spinner": {"style": "npm_dots"},
        "message": {"shimmer": {"enabled": True, "width": 3}},
        "progress": {"format": {"style": "percentage"}}
    },
    "states": {
        "success": {
            "spinner": {"icon": "โœ“", "color": "#00FF00"},
            "message": {"text": "Complete!"}
        }
    }
}
spinner = ThothSpinner.from_dict(config)

๐Ÿ› ๏ธ Development

Project Structure

thothspinner/
โ”œโ”€โ”€ src/thothspinner/       # Source code
โ”‚   โ”œโ”€โ”€ rich/               # Rich-based components
โ”‚   โ”‚   โ”œโ”€โ”€ components/     # Individual components
โ”‚   โ”‚   โ””โ”€โ”€ thothspinner.py # Main orchestrator
โ”‚   โ””โ”€โ”€ textual/            # Textual widgets
โ”œโ”€โ”€ tests/                  # Test suite (97%+ coverage)
โ”œโ”€โ”€ docs/                   # Documentation
โ”‚   โ”œโ”€โ”€ thothspinner_rich.md     # Rich API reference
โ”‚   โ”œโ”€โ”€ thothspinner_textual.md  # Textual API reference
โ”‚   โ”œโ”€โ”€ examples/                # Example scripts
โ”‚   โ””โ”€โ”€ troubleshooting.md       # Troubleshooting guide
โ”œโ”€โ”€ examples/               # Demo scripts
โ”œโ”€โ”€ justfile                # Task automation
โ””โ”€โ”€ pyproject.toml          # Project configuration

Development Commands

# Format code
just format

# Lint code
just lint

# Type check
just typecheck

# Run tests with coverage
just test-cov

# Security scan (bandit)
just security

# Generate changelog (git-cliff)
just changelog

# Version management
just current-version
just bump-patch
just bump-minor
just bump-major

# Regenerate visual regression snapshots
just update-snapshots

# Run all checks (format, lint, typecheck, security, test)
just all

# Clean build artifacts
just clean

CLI Tools

# Preview all 48 spinner styles
uv run thothspinner preview

# Preview a specific style
uv run thothspinner preview npm_dots

# Open interactive TUI style browser
uv run thothspinner browse

Generating the Demo GIF

# Install GIF generation tools (macOS only, one-time)
just install-readme-animation

# Generate demo.gif
just demo-gif

# Verify it looks right
open docs/images/demo.gif

# Commit and push
git add docs/images/demo.gif
git commit -m "docs: add demo.gif for README"
git push origin main

Testing

The project maintains 97%+ test coverage, including visual regression tests via pytest-textual-snapshot:

# Run tests
just test

# Run tests with coverage report
just test-cov
# Coverage report generated at htmlcov/index.html

# Run specific test file
just test tests/rich/test_spinner.py

# Regenerate visual regression snapshots (Textual widgets)
just update-snapshots

๐Ÿ“– Examples

Basic Progress Bar

from thothspinner import ThothSpinner
from rich.live import Live

with Live(ThothSpinner()) as live:
    spinner = live.renderable
    spinner.start()

    for i in range(100):
        spinner.update_progress(current=i, total=100)
        time.sleep(0.05)

    spinner.success()

File Processing

from pathlib import Path

files = list(Path(".").glob("*.py"))
spinner = ThothSpinner(progress_format="fraction")

with Live(spinner) as live:
    spinner.start()

    for i, file in enumerate(files):
        spinner.set_message(text=f"Processing {file.name}")  # rotating message update
        spinner.update_progress(current=i, total=len(files))
        process_file(file)

    spinner.success(f"Processed {len(files)} files")

Error Handling

with Live(ThothSpinner()) as live:
    spinner = live.renderable
    spinner.start()

    try:
        risky_operation()
        spinner.success("Operation successful")
    except Exception as e:
        spinner.error(f"Operation failed: {e}")

More examples in the Examples Gallery.

๐Ÿ—บ๏ธ Roadmap

Completed Milestones

โœ… M01โ€“M05: Core Rich Components (v0.1.0โ€“v0.5.0)

  • Hint, Spinner, Progress, Timer, and Message components
  • ThothSpinner orchestrator with state management
  • 97%+ test coverage, thread-safe operations with proper locking

โœ… M06: Rich Documentation (v0.6.0)

  • Comprehensive API reference, examples gallery with 20+ examples, troubleshooting guide

โœ… M07โ€“M13: Textual Components & Documentation (v0.7.0โ€“v0.13.0)

  • Full Textual widget set with reactive state management
  • Feature parity with all Rich components
  • Textual examples, integration guides, and API reference

โœ… M15: Progress Bar Format & Animation Smoothing (v1.1.0)

  • Bar format style for Textual ProgressWidget with configurable fill characters
  • Smooth animated transitions when progress values change

โœ… M14: Publishing to PyPI (v1.0.0)

  • PyPI package publication with OIDC trusted publishing
  • GitHub Actions CI/CD pipeline (test matrix, CodeQL, publish)
  • Release automation with git-cliff changelog generation

Releasing

First time? Follow the First-Time Publish Guide for step-by-step OIDC setup and the v1.0.0 publish walkthrough.

For subsequent releases, see the Release Guide. Quick reference:

# 1. Bump version (pick one), then run checks and commit:
just bump-patch          # or bump-minor / bump-major
just all                 # format, lint, typecheck, security, test โ€” must all pass
git add pyproject.toml
git commit -m "chore: release v1.2.3"
git push origin main

# 2. Tag and publish (auto-generates changelog, builds, tags, pushes โ†’ triggers CI โ†’ PyPI)
just release 1.2.3

Releases are published automatically via OIDC trusted publishing โ€” no API tokens required. See RELEASE.md for OIDC setup, CI/CD pipeline details, and troubleshooting.

๐Ÿค Contributing

Contributions are welcome! See CONTRIBUTING.md for full details. Quick summary:

  1. Check the MILESTONES.md for current tasks
  2. Follow the established code patterns
  3. Maintain test coverage above 90%
  4. Use the development toolchain (just commands)
  5. Write tests for new features
  6. Update documentation as needed

For milestone-specific work, reference tasks in the milestone documents (M01.md, M02.md, etc.).

Zero-Setup with GitHub Codespaces

A .devcontainer config is included โ€” open in Codespaces or VS Code Dev Containers for an instant, pre-configured development environment.

๐Ÿ“„ License

MIT License - See LICENSE file for details.

๐Ÿ™ Acknowledgments

  • Built on the excellent Rich and Textual libraries by Will McGugan
  • Inspired by various terminal UI libraries including ora, cli-spinners, and progress
  • Name inspired by Thoth, ancient Egyptian deity of wisdom and writing
  • Development patterns influenced by Rich's battle-tested implementation

๐Ÿ’ฌ Support

For issues, questions, or suggestions:


Current Version: 1.0.0 | Python: 3.11+ | Coverage: 97%+ | Rich Docs | Textual Docs

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

thothspinner-1.2.5.tar.gz (48.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

thothspinner-1.2.5-py3-none-any.whl (66.1 kB view details)

Uploaded Python 3

File details

Details for the file thothspinner-1.2.5.tar.gz.

File metadata

  • Download URL: thothspinner-1.2.5.tar.gz
  • Upload date:
  • Size: 48.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for thothspinner-1.2.5.tar.gz
Algorithm Hash digest
SHA256 caf05da508c366f49b00165006560a3d9276ad63d18944d8d7ae0857d543ce1a
MD5 a888c2586c2b2a46354004b6af6310f6
BLAKE2b-256 460b715d23e806dfa78fbe499d800c763458d0377993aaba0cd1046c4457ec4c

See more details on using hashes here.

File details

Details for the file thothspinner-1.2.5-py3-none-any.whl.

File metadata

  • Download URL: thothspinner-1.2.5-py3-none-any.whl
  • Upload date:
  • Size: 66.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for thothspinner-1.2.5-py3-none-any.whl
Algorithm Hash digest
SHA256 90bbbfcf003655c64bcb2573c364bd76da83d5e96f42fb7b19b5d36275ca739b
MD5 958046bda249352105ccbaa56c0a75a9
BLAKE2b-256 93314f26fc77295b289e52493892b0a93af214e261ae13f158bc21577b70a2fe

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page