mirror of
https://github.com/Aider-AI/aider.git
synced 2025-05-30 17:24:59 +00:00
refactor: Extract WaitingSpinner to its own module
This commit is contained in:
parent
80f78ee85d
commit
21a05ead4e
2 changed files with 65 additions and 15 deletions
|
@ -13,7 +13,7 @@ from rich.syntax import Syntax
|
||||||
from rich.text import Text
|
from rich.text import Text
|
||||||
|
|
||||||
from aider.dump import dump # noqa: F401
|
from aider.dump import dump # noqa: F401
|
||||||
from aider.utils import Spinner
|
from aider.waiting import WaitingSpinner
|
||||||
|
|
||||||
_text_prefix = """
|
_text_prefix = """
|
||||||
# Header
|
# Header
|
||||||
|
@ -117,12 +117,11 @@ class MarkdownStream:
|
||||||
else:
|
else:
|
||||||
self.mdargs = dict()
|
self.mdargs = dict()
|
||||||
|
|
||||||
# Defer Live creation until the first update so the Spinner can be shown.
|
# Defer Live creation until the first update so the spinner can be shown.
|
||||||
self.live = None
|
self.live = None
|
||||||
self.spinner = Spinner("Waiting for LLM")
|
self.waiting_spinner = WaitingSpinner("Waiting for LLM")
|
||||||
self._spinner_stop_event = threading.Event()
|
self.waiting_spinner.start()
|
||||||
self._spinner_thread = threading.Thread(target=self._spin, daemon=True)
|
self._spinner_running = True
|
||||||
self._spinner_thread.start()
|
|
||||||
self._live_started = False
|
self._live_started = False
|
||||||
|
|
||||||
def _spin(self):
|
def _spin(self):
|
||||||
|
@ -159,12 +158,10 @@ class MarkdownStream:
|
||||||
except Exception:
|
except Exception:
|
||||||
pass # Ignore any errors during cleanup
|
pass # Ignore any errors during cleanup
|
||||||
|
|
||||||
# Ensure the spinner thread is properly shut down
|
# Ensure the spinner is properly shut down
|
||||||
if hasattr(self, "_spinner_stop_event"):
|
if getattr(self, "_spinner_running", False):
|
||||||
self._spinner_stop_event.set()
|
|
||||||
if hasattr(self, "_spinner_thread") and self._spinner_thread.is_alive():
|
|
||||||
try:
|
try:
|
||||||
self._spinner_thread.join(timeout=0.1)
|
self.waiting_spinner.stop()
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -187,10 +184,9 @@ class MarkdownStream:
|
||||||
"""
|
"""
|
||||||
# On the first call, stop the spinner and start the Live renderer
|
# On the first call, stop the spinner and start the Live renderer
|
||||||
if not getattr(self, "_live_started", False):
|
if not getattr(self, "_live_started", False):
|
||||||
if hasattr(self, "_spinner_stop_event"):
|
if getattr(self, "_spinner_running", False):
|
||||||
self._spinner_stop_event.set()
|
self.waiting_spinner.stop()
|
||||||
if hasattr(self, "_spinner_thread"):
|
self._spinner_running = False
|
||||||
self._spinner_thread.join()
|
|
||||||
self.live = Live(Text(""), refresh_per_second=1.0 / self.min_delay)
|
self.live = Live(Text(""), refresh_per_second=1.0 / self.min_delay)
|
||||||
self.live.start()
|
self.live.start()
|
||||||
self._live_started = True
|
self._live_started = True
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
Thread-based, killable spinner utility.
|
||||||
|
|
||||||
|
Use it like:
|
||||||
|
|
||||||
|
from aider.waiting import WaitingSpinner
|
||||||
|
|
||||||
|
spinner = WaitingSpinner("Waiting for LLM")
|
||||||
|
spinner.start()
|
||||||
|
... # long task
|
||||||
|
spinner.stop()
|
||||||
|
"""
|
||||||
|
|
||||||
|
import threading
|
||||||
|
import time
|
||||||
|
|
||||||
|
from aider.utils import Spinner
|
||||||
|
|
||||||
|
|
||||||
|
class WaitingSpinner:
|
||||||
|
"""Background spinner that can be started/stopped safely."""
|
||||||
|
|
||||||
|
def __init__(self, text: str = "Waiting for LLM", delay: float = 0.15):
|
||||||
|
self.spinner = Spinner(text)
|
||||||
|
self.delay = delay
|
||||||
|
self._stop_event = threading.Event()
|
||||||
|
self._thread = threading.Thread(target=self._spin, daemon=True)
|
||||||
|
|
||||||
|
def _spin(self):
|
||||||
|
while not self._stop_event.is_set():
|
||||||
|
time.sleep(self.delay)
|
||||||
|
self.spinner.step()
|
||||||
|
self.spinner.end()
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
"""Start the spinner in a background thread."""
|
||||||
|
if not self._thread.is_alive():
|
||||||
|
self._thread.start()
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
"""Request the spinner to stop and wait briefly for the thread to exit."""
|
||||||
|
self._stop_event.set()
|
||||||
|
if self._thread.is_alive():
|
||||||
|
self._thread.join(timeout=0.1)
|
||||||
|
|
||||||
|
# Allow use as a context-manager
|
||||||
|
def __enter__(self):
|
||||||
|
self.start()
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||||
|
self.stop()
|
Loading…
Add table
Add a link
Reference in a new issue