How to get a Rich spinner to update with minimal code in a Textual app?

I have a very minimal Textual app which displays a Rich spinner, but doesn’t update it. Can someone please tell me what I’ve missed? Here’s the code for the app:

from rich.live import Live
from rich.spinner import Spinner
from textual.app import App, ComposeResult
from textual.widgets import Static

class SpinnerStatic(Static):
    def __init__(self, spinner, **kwargs):
        super().__init__(**kwargs)
        self.spinner = spinner
        self.live = Live(spinner)

    def on_mount(self):
        self.update(self.spinner)
        self.live.start()

class TestApp(App):
    def compose(self) -> ComposeResult:
        spinner = Spinner('dots', speed=1.0)
        w = SpinnerStatic(spinner)
        yield w

app = TestApp()
app.run()

I’ve assumed that the defaults will suffice for the refresh interval, etc. that I haven;t specified.

So one thing that can be tough with Textual apps is that sometimes an exception is thrown, but you can’t see it because textual has control of the screen. But when I run your script and then control-C out I get a stack trace that ends with
rich.errors.LiveError: Only one live display may be active at once
so I am guessing that maybe the Static widget (or something else) already has a Live context running.

I was able to make this work by using a set_interval event. You’ll want to set the interval as high as possible while still getting the fluidity you want

class SpinnerStatic(Static):
    def __init__(self, spinner, **kwargs):
        super().__init__(**kwargs)
        self.spinner = spinner

    def on_mount(self):
        self.set_interval(.05, lambda: self.update(self.spinner))
2 Likes

Thanks for the suggestion!