mirror of
https://github.com/Textualize/textual.git
synced 2025-10-17 02:38:12 +03:00
eof
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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>"]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,25 +146,30 @@ 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:
|
||||
|
||||
self.disable_input()
|
||||
with timer("disable_input"):
|
||||
self.disable_input()
|
||||
|
||||
if self.attrs_before is not None:
|
||||
try:
|
||||
termios.tcsetattr(self.fileno, termios.TCSANOW, self.attrs_before)
|
||||
except termios.error:
|
||||
pass
|
||||
with timer("tcsetattr"):
|
||||
if self.attrs_before is not None:
|
||||
try:
|
||||
termios.tcsetattr(self.fileno, termios.TCSANOW, self.attrs_before)
|
||||
except termios.error:
|
||||
pass
|
||||
|
||||
self.console.set_alt_screen(False)
|
||||
self.console.show_cursor(True)
|
||||
with timer("set_alt_screen False, show cursor"):
|
||||
with self.console:
|
||||
self.console.set_alt_screen(False)
|
||||
self.console.show_cursor(True)
|
||||
|
||||
def run_input_thread(self, loop) -> None:
|
||||
try:
|
||||
@@ -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,11 +205,11 @@ 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:
|
||||
selector.close()
|
||||
with timer("selector.close"):
|
||||
selector.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user