This commit is contained in:
Will McGugan
2022-01-01 14:48:28 +00:00
parent f47b3e089c
commit 15fee1f5ac
6 changed files with 65 additions and 39 deletions

View File

@@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
## [0.1.13] - 2022-01-01
### Fixed
- Fixed spurious characters when exiting app
- Fixed increasing delay when exiting
## [0.1.12] - 2021-09-20
### Added

View File

@@ -1,6 +1,6 @@
[tool.poetry]
name = "textual"
version = "0.1.12"
version = "0.1.13"
homepage = "https://github.com/willmcgugan/textual"
description = "Text User Interface using Rich"
authors = ["Will McGugan <willmcgugan@gmail.com>"]

View File

@@ -113,10 +113,10 @@ class Animator:
async def start(self) -> None:
if self._timer_task is None:
self._timer_task = asyncio.get_event_loop().create_task(self._timer.run())
self._timer_task = self._timer.start()
async def stop(self) -> None:
self._timer.stop()
await self._timer.stop()
if self._timer_task:
await self._timer_task
self._timer_task = None

View File

@@ -7,7 +7,6 @@ import selectors
import signal
import sys
import termios
from time import time
import tty
from typing import Any, TYPE_CHECKING
from threading import Event, Thread
@@ -15,12 +14,14 @@ from threading import Event, Thread
if TYPE_CHECKING:
from rich.console import Console
from . import log
from . import events
from .driver import Driver
from .geometry import Size
from ._types import MessageTarget
from ._xterm_parser import XTermParser
from ._profile import timer
class LinuxDriver(Driver):
@@ -53,7 +54,7 @@ class LinuxDriver(Driver):
write("\x1b[?1006h") # SET_SGR_EXT_MODE_MOUSE
# write("\x1b[?1007h")
# self.console.file.flush()
self.console.file.flush()
# Note: E.g. lxterminal understands 1000h, but not the urxvt or sgr
# extensions.
@@ -64,7 +65,7 @@ class LinuxDriver(Driver):
write("\x1b[?1003l") #
write("\x1b[?1015l")
write("\x1b[?1006l")
# self.console.file.flush()
self.console.file.flush()
def start_application_mode(self):
@@ -110,7 +111,7 @@ class LinuxDriver(Driver):
self.console.show_cursor(False)
self.console.file.write("\033[?1003h\n")
self.console.file.flush()
self._key_thread = Thread(
target=self.run_input_thread, args=(asyncio.get_event_loop(),)
)
@@ -145,23 +146,28 @@ class LinuxDriver(Driver):
if not self.exit_event.is_set():
signal.signal(signal.SIGWINCH, signal.SIG_DFL)
self._disable_mouse_support()
termios.tcflush(self.fileno, termios.TCIFLUSH)
self.exit_event.set()
if self._key_thread is not None:
self._key_thread.join()
except Exception:
except Exception as error:
# TODO: log this
pass
def stop_application_mode(self) -> None:
with timer("disable_input"):
self.disable_input()
with timer("tcsetattr"):
if self.attrs_before is not None:
try:
termios.tcsetattr(self.fileno, termios.TCSANOW, self.attrs_before)
except termios.error:
pass
with timer("set_alt_screen False, show cursor"):
with self.console:
self.console.set_alt_screen(False)
self.console.show_cursor(True)
@@ -180,7 +186,7 @@ class LinuxDriver(Driver):
def more_data() -> bool:
"""Check if there is more data to parse."""
for key, events in selector.select(0.1):
for key, events in selector.select(0.01):
if events:
return True
return False
@@ -199,10 +205,10 @@ class LinuxDriver(Driver):
unicode_data = decode(read(fileno, 1024))
for event in parser.feed(unicode_data):
self.process_event(event)
except Exception:
pass
# TODO: log
except Exception as error:
log(error)
finally:
with timer("selector.close"):
selector.close()

View File

@@ -1,7 +1,13 @@
from __future__ import annotations
import weakref
from asyncio import CancelledError, Event, TimeoutError, wait_for
from asyncio import (
get_event_loop,
CancelledError,
Event,
sleep,
Task,
)
from time import monotonic
from typing import Awaitable, Callable, Union
@@ -42,7 +48,6 @@ class Timer:
self._callback = callback
self._repeat = repeat
self._skip = skip
self._stop_event = Event()
self._active = Event()
if not pause:
self._active.set()
@@ -59,22 +64,33 @@ class Timer:
raise EventTargetGone()
return target
def stop(self) -> None:
self._active.set()
self._stop_event.set()
def start(self) -> Task:
"""Start the timer return the task.
Returns:
Task: A Task instance for the timer.
"""
self._task = get_event_loop().create_task(self._run())
return self._task
async def stop(self) -> None:
"""Stop the timer, and block until it exists."""
self._task.cancel()
await self._task
def pause(self) -> None:
"""Pause the timer."""
self._active.clear()
def resume(self) -> None:
"""Result a paused timer."""
self._active.set()
async def run(self) -> None:
async def _run(self) -> None:
"""Run the timer."""
count = 0
_repeat = self._repeat
_interval = self._interval
_wait = self._stop_event.wait
_wait_active = self._active.wait
start = monotonic()
try:
while _repeat is None or count <= _repeat:
@@ -82,11 +98,9 @@ class Timer:
if self._skip and next_timer < monotonic():
count += 1
continue
try:
if await wait_for(_wait(), max(0, next_timer - monotonic())):
break
except TimeoutError:
pass
wait_time = max(0, next_timer - monotonic())
if wait_time:
await sleep(wait_time)
event = events.Timer(
self.sender, timer=self, count=count, callback=self._callback
)
@@ -95,7 +109,6 @@ class Timer:
await self.target.post_message(event)
except EventTargetGone:
break
await _wait_active()
await self._active.wait()
except CancelledError:
pass

View File

@@ -127,8 +127,7 @@ class MessagePump:
name: str | None = None,
) -> Timer:
timer = Timer(self, delay, self, name=name, callback=callback, repeat=0)
timer_task = asyncio.get_event_loop().create_task(timer.run())
self._child_tasks.add(timer_task)
self._child_tasks.add(timer.start())
return timer
def set_interval(
@@ -142,7 +141,7 @@ class MessagePump:
timer = Timer(
self, interval, self, name=name, callback=callback, repeat=repeat or None
)
self._child_tasks.add(asyncio.get_event_loop().create_task(timer.run()))
self._child_tasks.add(timer.start())
return timer
async def call_later(self, callback: Callable, *args, **kwargs) -> None: