Merge pull request #881 from Textualize/win-slow

Win slow
This commit is contained in:
Will McGugan
2022-10-12 15:34:06 +01:00
committed by GitHub
12 changed files with 61 additions and 47 deletions

View File

@@ -43,28 +43,28 @@ class Logger:
self._group = group
self._verbosity = verbosity
@property
def log(self) -> LogCallable:
if self._log is None:
try:
app = active_app.get()
except LookupError:
raise LoggerError("Unable to log without an active app.") from None
return app._log
return self._log
def __rich_repr__(self) -> rich.repr.Result:
yield self._group, LogGroup.INFO
yield self._verbosity, LogVerbosity.NORMAL
def __call__(self, *args: object, **kwargs) -> None:
caller = inspect.stack()[1]
try:
self.log(
app = active_app.get()
except LookupError:
raise LoggerError("Unable to log without an active app.") from None
if not app.devtools.is_connected:
return
previous_frame = inspect.currentframe().f_back
caller = inspect.getframeinfo(previous_frame)
_log = self._log or app._log
try:
_log(
self._group,
self._verbosity,
caller,
*args,
_textual_calling_frame=caller,
**kwargs,
)
except LoggerError:

View File

@@ -1,5 +1,6 @@
import asyncio
from time import monotonic
from ._time import time
"""
@@ -14,16 +15,15 @@ by mocking the few functions exposed by this module.
# (so mocking public APIs such as `get_time` wouldn't affect direct references to then that were done during imports)
class _Clock:
async def get_time(self) -> float:
return self.get_time_no_wait()
return time()
def get_time_no_wait(self) -> float:
return monotonic()
return time()
async def sleep(self, seconds: float) -> None:
await asyncio.sleep(seconds)
# That's our target for mocking time! :-)
_clock = _Clock()

View File

@@ -3,10 +3,9 @@ Timer context manager, only used in debug.
"""
from time import time
import contextlib
from typing import Generator
from time import perf_counter
from . import log
@@ -14,8 +13,8 @@ from . import log
@contextlib.contextmanager
def timer(subject: str = "time") -> Generator[None, None, None]:
"""print the elapsed time. (only used in debugging)"""
start = time()
start = perf_counter()
yield
elapsed = time() - start
elapsed = perf_counter() - start
elapsed_ms = elapsed * 1000
log(f"{subject} elapsed {elapsed_ms:.2f}ms")

12
src/textual/_time.py Normal file
View File

@@ -0,0 +1,12 @@
import platform
from time import monotonic, perf_counter
PLATFORM = platform.system()
WINDOWS = PLATFORM == "Windows"
if WINDOWS:
time = perf_counter
else:
time = monotonic

View File

@@ -513,8 +513,8 @@ class App(Generic[ReturnType], DOMNode):
self,
group: LogGroup,
verbosity: LogVerbosity,
_textual_calling_frame: inspect.FrameInfo,
*objects: Any,
_textual_calling_frame: inspect.FrameInfo | None = None,
**kwargs,
) -> None:
"""Write to logs or devtools.
@@ -539,9 +539,6 @@ class App(Generic[ReturnType], DOMNode):
if verbosity.value > LogVerbosity.NORMAL.value and not self.devtools.verbose:
return
if not _textual_calling_frame:
_textual_calling_frame = inspect.stack()[1]
try:
if len(objects) == 1 and not kwargs:
self.devtools.log(

View File

@@ -3,12 +3,11 @@ from __future__ import annotations
import asyncio
import inspect
import json
import pickle
from time import time
from asyncio import Queue, Task, QueueFull
from asyncio import Queue, QueueFull, Task
from io import StringIO
from typing import Type, Any, NamedTuple
from time import time
from typing import Any, NamedTuple, Type
from rich.console import Console
from rich.segment import Segment
@@ -22,12 +21,12 @@ class DevtoolsDependenciesMissingError(Exception):
try:
import aiohttp
import msgpack
from aiohttp import (
ClientResponseError,
ClientConnectorError,
ClientResponseError,
ClientWebSocketResponse,
)
import msgpack
except ImportError:
# TODO: Add link to documentation on how to install devtools
raise DevtoolsDependenciesMissingError(

View File

@@ -39,7 +39,9 @@ class StdoutRedirector:
if not self.devtools.is_connected:
return
caller = inspect.stack()[1]
previous_frame = inspect.currentframe().f_back
caller = inspect.getframeinfo(previous_frame)
self._buffer.append(DevtoolsLog(string, caller=caller))
# By default, `print` adds a "\n" suffix which results in a buffer

View File

@@ -6,7 +6,6 @@ import base64
import json
import pickle
from json import JSONDecodeError
from time import time
from typing import cast
from aiohttp import WSMessage, WSMsgType
@@ -17,6 +16,7 @@ from rich.markup import escape
import msgpack
from textual._log import LogGroup
from textual._time import time
from textual.devtools.renderables import (
DevConsoleLog,
DevConsoleNotice,

View File

@@ -1,11 +1,10 @@
from __future__ import annotations
import asyncio
from time import time
from abc import ABC, abstractmethod
from typing import TYPE_CHECKING
from . import events
from . import _clock, events
from ._types import MessageTarget
if TYPE_CHECKING:
@@ -20,7 +19,7 @@ class Driver(ABC):
self._target = target
self._debug = debug
self._loop = asyncio.get_running_loop()
self._mouse_down_time = time()
self._mouse_down_time = _clock.get_time_no_wait()
def send_event(self, event: events.Event) -> None:
asyncio.run_coroutine_threadsafe(

View File

@@ -263,6 +263,11 @@ class EventMonitor(threading.Thread):
key_event = input_record.Event.KeyEvent
key = key_event.uChar.UnicodeChar
if key_event.bKeyDown or key == "\x1b":
if (
key_event.dwControlKeyState
and key_event.wVirtualKeyCode == 0
):
continue
append_key(key)
elif event_type == WINDOW_BUFFER_SIZE_EVENT:
# Window size changed, store size

View File

@@ -10,21 +10,20 @@ from __future__ import annotations
import asyncio
import inspect
from asyncio import CancelledError, Queue, QueueEmpty, Task
from time import time
from functools import partial
from typing import TYPE_CHECKING, Any, Awaitable, Callable, Iterable
from weakref import WeakSet
from . import events, log, messages, Logger
from . import Logger, events, log, messages
from ._callback import invoke
from ._context import NoActiveAppError, active_app
from .errors import DuplicateKeyHandlers
from .keys import _get_key_aliases
from .timer import Timer, TimerCallback
from ._time import time
from .case import camel_to_snake
from .errors import DuplicateKeyHandlers
from .events import Event
from .message import Message
from .reactive import Reactive
from .timer import Timer, TimerCallback
if TYPE_CHECKING:
from .app import App

View File

@@ -461,14 +461,16 @@ class Widget(DOMNode):
self.highlight_link_id = hover_style.link_id
def watch_scroll_x(self, new_value: float) -> None:
self.horizontal_scrollbar.position = int(new_value)
self.refresh(layout=True)
self.horizontal_scrollbar.refresh()
if self.show_horizontal_scrollbar:
self.horizontal_scrollbar.position = int(new_value)
self.horizontal_scrollbar.refresh()
self.refresh(layout=True)
def watch_scroll_y(self, new_value: float) -> None:
self.vertical_scrollbar.position = int(new_value)
self.refresh(layout=True)
self.vertical_scrollbar.refresh()
if self.show_vertical_scrollbar:
self.vertical_scrollbar.position = int(new_value)
self.vertical_scrollbar.refresh()
self.refresh(layout=True)
def validate_scroll_x(self, value: float) -> float:
return clamp(value, 0, self.max_scroll_x)