|
"""A simple spinner module""" |
|
import itertools |
|
import sys |
|
import threading |
|
import time |
|
|
|
|
|
class Spinner: |
|
"""A simple spinner class""" |
|
|
|
def __init__(self, message: str = "Loading...", delay: float = 0.1) -> None: |
|
"""Initialize the spinner class |
|
|
|
Args: |
|
message (str): The message to display. |
|
delay (float): The delay between each spinner update. |
|
""" |
|
self.spinner = itertools.cycle(["-", "/", "|", "\\"]) |
|
self.delay = delay |
|
self.message = message |
|
self.running = False |
|
self.spinner_thread = None |
|
|
|
def spin(self) -> None: |
|
"""Spin the spinner""" |
|
while self.running: |
|
sys.stdout.write(f"{next(self.spinner)} {self.message}\r") |
|
sys.stdout.flush() |
|
time.sleep(self.delay) |
|
sys.stdout.write(f"\r{' ' * (len(self.message) + 2)}\r") |
|
|
|
def __enter__(self): |
|
"""Start the spinner""" |
|
self.running = True |
|
self.spinner_thread = threading.Thread(target=self.spin) |
|
self.spinner_thread.start() |
|
|
|
return self |
|
|
|
def __exit__(self, exc_type, exc_value, exc_traceback) -> None: |
|
"""Stop the spinner |
|
|
|
Args: |
|
exc_type (Exception): The exception type. |
|
exc_value (Exception): The exception value. |
|
exc_traceback (Exception): The exception traceback. |
|
""" |
|
self.running = False |
|
if self.spinner_thread is not None: |
|
self.spinner_thread.join() |
|
sys.stdout.write(f"\r{' ' * (len(self.message) + 2)}\r") |
|
sys.stdout.flush() |
|
|
|
def update_message(self, new_message, delay=0.1): |
|
"""Update the spinner message |
|
Args: |
|
new_message (str): New message to display |
|
delay: Delay in seconds before updating the message |
|
""" |
|
time.sleep(delay) |
|
sys.stdout.write( |
|
f"\r{' ' * (len(self.message) + 2)}\r" |
|
) |
|
sys.stdout.flush() |
|
self.message = new_message |
|
|