mirror of
https://github.com/Textualize/textual.git
synced 2025-10-17 02:38:12 +03:00
fix shutdown
This commit is contained in:
@@ -65,11 +65,12 @@ class XTermParser(Parser[events.Event]):
|
||||
|
||||
while not self.is_eof:
|
||||
character = yield read1()
|
||||
log.debug("character=%r", character)
|
||||
if character == ESC and ((yield self.peek_buffer()) or more_data()):
|
||||
sequence: str = character
|
||||
while True:
|
||||
sequence += yield read1()
|
||||
log.debug(f"sequence={sequence!r}")
|
||||
log.debug(f"sequence=%r", sequence)
|
||||
keys = get_ansi_sequence(sequence, None)
|
||||
if keys is not None:
|
||||
for key in keys:
|
||||
|
||||
@@ -113,13 +113,10 @@ class App(MessagePump):
|
||||
except Exception:
|
||||
log.exception("error starting application mode")
|
||||
raise
|
||||
try:
|
||||
await super().process_messages()
|
||||
finally:
|
||||
try:
|
||||
driver.stop_application_mode()
|
||||
finally:
|
||||
loop.remove_signal_handler(signal.SIGINT)
|
||||
await super().process_messages()
|
||||
|
||||
await self.view.close_messages()
|
||||
driver.stop_application_mode()
|
||||
|
||||
async def add(self, child: MessagePump) -> None:
|
||||
self.children.add(child)
|
||||
@@ -132,45 +129,16 @@ class App(MessagePump):
|
||||
async def shutdown(self):
|
||||
driver = self._driver
|
||||
driver.disable_input()
|
||||
|
||||
async def shutdown_procedure() -> None:
|
||||
log.debug("1")
|
||||
await self.stop_messages()
|
||||
log.debug("2")
|
||||
await self.view.stop_messages()
|
||||
log.debug("3")
|
||||
log.debug("4")
|
||||
await self.remove(self.view)
|
||||
if self.children:
|
||||
log.debug("5")
|
||||
|
||||
async def close_all() -> None:
|
||||
for child in self.children:
|
||||
await child.close_messages(wait=False)
|
||||
await asyncio.gather(*(child.task for child in self.children))
|
||||
|
||||
try:
|
||||
await asyncio.wait_for(close_all(), timeout=5)
|
||||
log.debug("6")
|
||||
except asyncio.TimeoutError as error:
|
||||
raise ShutdownError("Timeout closing messages pump(s)") from None
|
||||
log.debug("7")
|
||||
|
||||
log.debug("8")
|
||||
await self.view.close_messages()
|
||||
log.debug("9")
|
||||
await self.close_messages()
|
||||
log.debug("10")
|
||||
|
||||
await asyncio.create_task(shutdown_procedure())
|
||||
await self.close_messages()
|
||||
|
||||
def refresh(self) -> None:
|
||||
console = self.console
|
||||
try:
|
||||
with console:
|
||||
console.print(Screen(Control.home(), self.view, Control.home()))
|
||||
except Exception:
|
||||
log.exception("refresh failed")
|
||||
if not self._closed:
|
||||
console = self.console
|
||||
try:
|
||||
with console:
|
||||
console.print(Screen(Control.home(), self.view, Control.home()))
|
||||
except Exception:
|
||||
log.exception("refresh failed")
|
||||
|
||||
async def on_event(self, event: events.Event) -> None:
|
||||
if isinstance(event, events.Key):
|
||||
|
||||
@@ -50,6 +50,7 @@ class EventType(Enum):
|
||||
CUSTOM = 1000
|
||||
|
||||
|
||||
@rich_repr
|
||||
class Event(Message):
|
||||
type: ClassVar[EventType]
|
||||
|
||||
|
||||
@@ -28,7 +28,6 @@ class MessagePump:
|
||||
self._pending_message: Message | None = None
|
||||
self._task: Task | None = None
|
||||
self._child_tasks: set[Task] = set()
|
||||
self._queue_empty_event = Event()
|
||||
|
||||
@property
|
||||
def task(self) -> Task:
|
||||
@@ -111,34 +110,16 @@ class MessagePump:
|
||||
asyncio.get_event_loop().create_task(timer.run())
|
||||
return timer
|
||||
|
||||
async def stop_messages(self) -> None:
|
||||
if not self._closing:
|
||||
await self.post_message(events.NoneEvent(self))
|
||||
self._closing = True
|
||||
return
|
||||
if not (self._closing or self._closed):
|
||||
self._queue_empty_event.clear()
|
||||
await self.post_message(events.NoneEvent(self))
|
||||
self._closing = True
|
||||
await self._queue_empty_event.wait()
|
||||
self._queue_empty_event.clear()
|
||||
|
||||
async def close_messages(self, wait: bool = True) -> None:
|
||||
"""Close message queue, and optionally wait for queue to finish processing."""
|
||||
if self._closed:
|
||||
return
|
||||
log.debug("close_messages %r wait=%r", self, wait)
|
||||
|
||||
self._closing = True
|
||||
log.debug("close 1 %r", self)
|
||||
await self._message_queue.put(None)
|
||||
|
||||
for task in self._child_tasks:
|
||||
task.cancel()
|
||||
log.debug("close 2 %r", self)
|
||||
await self._message_queue.put(None)
|
||||
log.debug("close 3 %r", self)
|
||||
if wait and self._task is not None:
|
||||
await self._task
|
||||
self._task = None
|
||||
log.debug("close 4 %r", self)
|
||||
|
||||
def start_messages(self) -> None:
|
||||
self._task = asyncio.create_task(self.process_messages())
|
||||
@@ -149,7 +130,6 @@ class MessagePump:
|
||||
try:
|
||||
message = await self.get_message()
|
||||
except MessagePumpClosed:
|
||||
log.debug("CLOSED %r", self)
|
||||
break
|
||||
except Exception as error:
|
||||
log.exception("error in get_message()")
|
||||
@@ -157,7 +137,7 @@ class MessagePump:
|
||||
|
||||
log.debug("%r -> %r", message, self)
|
||||
# Combine any pending messages that may supersede this one
|
||||
while True:
|
||||
while not (self._closed or self._closing):
|
||||
pending = self.peek_message()
|
||||
if pending is None or not message.can_batch(pending):
|
||||
break
|
||||
@@ -172,21 +152,14 @@ class MessagePump:
|
||||
log.exception("error in dispatch_message")
|
||||
raise
|
||||
finally:
|
||||
log.debug("a")
|
||||
if self._message_queue.empty():
|
||||
log.debug("b")
|
||||
self._queue_empty_event.set()
|
||||
if not self._closed:
|
||||
idle_handler = getattr(self, "on_idle", None)
|
||||
log.debug("c %r", idle_handler)
|
||||
if idle_handler is not None and not self._closed:
|
||||
log.debug("d")
|
||||
await idle_handler(events.Idle(self))
|
||||
log.debug("e")
|
||||
self._queue_empty_event.set()
|
||||
log.debug("CLOSED %r", self)
|
||||
|
||||
async def dispatch_message(self, message: Message) -> bool | None:
|
||||
log.debug("dispatch_message %r", message)
|
||||
if isinstance(message, events.Event):
|
||||
await self.on_event(message)
|
||||
else:
|
||||
@@ -196,7 +169,6 @@ class MessagePump:
|
||||
async def on_event(self, event: events.Event) -> None:
|
||||
method_name = f"on_{event.name}"
|
||||
dispatch_function: MessageHandler = getattr(self, method_name, None)
|
||||
log.debug("dispatching to %r", dispatch_function)
|
||||
if dispatch_function is not None:
|
||||
await dispatch_function(event)
|
||||
if event.bubble and self._parent and not event._stop_propagaton:
|
||||
@@ -217,15 +189,11 @@ class MessagePump:
|
||||
return True
|
||||
|
||||
async def post_message(self, message: Message) -> bool:
|
||||
log.debug("%r post_message 1", self)
|
||||
if self._closing or self._closed:
|
||||
return False
|
||||
log.debug("%r post_message 2", self)
|
||||
if not self.check_message_enabled(message):
|
||||
return True
|
||||
log.debug("%r post_message 3", self)
|
||||
await self._message_queue.put(message)
|
||||
log.debug("%r post_message 4", self)
|
||||
return True
|
||||
|
||||
async def post_message_from_child(self, message: Message) -> bool:
|
||||
|
||||
Reference in New Issue
Block a user