From 764bc21afed0888e28ed13463ace8417673197ae Mon Sep 17 00:00:00 2001 From: Tristan Simas Date: Fri, 6 Nov 2026 14:00:20 -0500 Subject: [PATCH] A headless driver has no terminal to ask for a palette HeadlessDriver inherited Driver.query_colours, which writes the OSC 10/11/4 queries and waits for their replies. The headless driver's write sends nowhere, so no reply can come, and every headless app that asked waited out the whole timeout before the same TerminalGaveNoPalette. Toad asks once at startup with a 0.25 s deadline, so each of its 594 app tests sat idle 0.25 s (about 2.5 minutes of a serial run). The headless driver now answers at once: its smallest app tests go from 1.18-1.23 s to 0.93-1.04 s. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01XbFMSqJMarXn2ZE8iAL7Sd --- src/textual/drivers/headless_driver.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/textual/drivers/headless_driver.py b/src/textual/drivers/headless_driver.py index 60e5f8bb0b8..1e4a1573570 100644 --- a/src/textual/drivers/headless_driver.py +++ b/src/textual/drivers/headless_driver.py @@ -3,7 +3,7 @@ import asyncio from textual import events -from textual.driver import Driver +from textual.driver import Driver, TerminalColours, TerminalGaveNoPalette from textual.geometry import Size @@ -41,6 +41,15 @@ def write(self, data: str) -> None: """ # Nothing to write as this is a headless driver. + async def query_colours(self, *, timeout: float) -> TerminalColours: + """There is no terminal to ask: the query goes nowhere, so no reply can come. + + The inherited query waited out its whole deadline for answers to writes that went + nowhere, so every headless app that asked (each of Toad's app tests, at startup) + sat idle for the full timeout before getting this same answer. + """ + raise TerminalGaveNoPalette("a headless driver has no terminal to ask for a palette") + def start_application_mode(self) -> None: """Start application mode.""" loop = asyncio.get_running_loop()