Fix NoMatches crash: buffer writes until OperationLog is mounted

The worker starts streaming output before the modal screen finishes
composing. Buffer writes until on_mount fires, then flush.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
shuki
2026-03-06 01:44:37 +02:00
parent 75f00f6521
commit 7793f02aa2

View File

@@ -1,3 +1,5 @@
import asyncio
from rich.text import Text from rich.text import Text
from textual.app import ComposeResult from textual.app import ComposeResult
from textual.screen import ModalScreen from textual.screen import ModalScreen
@@ -12,6 +14,8 @@ class OperationLog(ModalScreen[None]):
def __init__(self, title: str = "Operation Output"): def __init__(self, title: str = "Operation Output"):
super().__init__() super().__init__()
self._title = title self._title = title
self._mounted_event = asyncio.Event()
self._buffer: list[str] = []
def compose(self) -> ComposeResult: def compose(self) -> ComposeResult:
with Vertical(id="op-log"): with Vertical(id="op-log"):
@@ -19,15 +23,32 @@ class OperationLog(ModalScreen[None]):
yield RichLog(id="ol-log", wrap=True, highlight=True, markup=True) yield RichLog(id="ol-log", wrap=True, highlight=True, markup=True)
yield Button("Close", variant="primary", id="ol-close") yield Button("Close", variant="primary", id="ol-close")
def on_mount(self) -> None:
# Flush any buffered writes
log = self.query_one("#ol-log", RichLog)
for text in self._buffer:
self._write_to_log(log, text)
self._buffer.clear()
self._mounted_event.set()
def on_button_pressed(self, event: Button.Pressed) -> None: def on_button_pressed(self, event: Button.Pressed) -> None:
self.dismiss(None) self.dismiss(None)
def action_close(self) -> None: def action_close(self) -> None:
self.dismiss(None) self.dismiss(None)
def write(self, text: str) -> None: def _write_to_log(self, log: RichLog, text: str) -> None:
log = self.query_one("#ol-log", RichLog)
if "[" in text and "[/" in text: if "[" in text and "[/" in text:
log.write(Text.from_markup(text)) log.write(Text.from_markup(text))
else: else:
log.write(text) log.write(text)
def write(self, text: str) -> None:
if not self._mounted_event.is_set():
self._buffer.append(text)
return
try:
log = self.query_one("#ol-log", RichLog)
self._write_to_log(log, text)
except Exception:
self._buffer.append(text)