From 37ee64a2245b769f204cff28683fab77398d7217 Mon Sep 17 00:00:00 2001 From: pmp-p Date: Sun, 26 Nov 2023 08:21:54 +0100 Subject: [PATCH 1/3] thread->async, res path --- src/textual/app.py | 40 ++++++++++++++++------------------------ src/textual/worker.py | 9 +++++++-- 2 files changed, 23 insertions(+), 26 deletions(-) diff --git a/src/textual/app.py b/src/textual/app.py index 630e7753ed..bc6a2ac4c9 100644 --- a/src/textual/app.py +++ b/src/textual/app.py @@ -96,12 +96,7 @@ from .notifications import Notification, Notifications, Notify, SeverityLevel from .reactive import Reactive from .renderables.blank import Blank -from .screen import ( - Screen, - ScreenResultCallbackType, - ScreenResultType, - _SystemModalScreen, -) +from .screen import Screen, ScreenResultCallbackType, ScreenResultType from .widget import AwaitMount, Widget from .widgets._toast import ToastRack from .worker import NoActiveWorker, get_current_worker @@ -479,14 +474,18 @@ def __init__( self.stylesheet = Stylesheet(variables=self.get_css_variables()) css_path = css_path or self.CSS_PATH - css_paths = [ - _make_path_object_relative(css_path, self) - for css_path in ( - _css_path_type_as_list(css_path) if css_path is not None else [] - ) - ] - self.css_path = css_paths + css_paths = [] + try: + css_paths.append(_make_path_object_relative(css_path, self)) + except OSError: + pass + for css_path in _css_path_type_as_list(css_path): + if css_path is not None: + css_paths.append(css_path) + else: + css_path.append([]) + self.css_path = css_paths self._registry: WeakSet[DOMNode] = WeakSet() # Sensitivity on X is double the sensitivity on Y to account for @@ -605,14 +604,8 @@ def children(self) -> Sequence["Widget"]: A sequence of widgets. """ try: - return ( - next( - screen - for screen in reversed(self._screen_stack) - if not isinstance(screen, _SystemModalScreen) - ), - ) - except StopIteration: + return (self.screen,) + except ScreenError: return () @contextmanager @@ -1143,7 +1136,7 @@ async def _press_keys(self, keys: Iterable[str]) -> None: for key in keys: if key.startswith("wait:"): _, wait_ms = key.split(":") - print(f"(pause {wait_ms}ms)") + #print(f"(pause {wait_ms}ms)") await asyncio.sleep(float(wait_ms) / 1000) else: if len(key) == 1 and not key.isalnum(): @@ -1154,7 +1147,7 @@ async def _press_keys(self, keys: Iterable[str]) -> None: char = unicodedata.lookup(_get_unicode_name_from_key(original_key)) except KeyError: char = key if len(key) == 1 else None - print(f"press {key!r} (char={char!r})") + #print(f"press {key!r} (char={char!r})") key_event = events.Key(key, char) key_event._set_sender(app) driver.send_event(key_event) @@ -2202,7 +2195,6 @@ async def invoke_ready_callback() -> None: self.check_idle() finally: self._mounted_event.set() - self._is_mounted = True Reactive._initialize_object(self) diff --git a/src/textual/worker.py b/src/textual/worker.py index 6e8a0234c3..011c3f95b2 100644 --- a/src/textual/worker.py +++ b/src/textual/worker.py @@ -3,7 +3,7 @@ """ from __future__ import annotations - +import sys import asyncio import enum import inspect @@ -163,7 +163,10 @@ def __init__( self.group = group self.description = description self.exit_on_error = exit_on_error - self._thread_worker = thread + if sys.platform in ('emscripten','wasi'): + self._thread_worker = False + else: + self._thread_worker = thread self._state = WorkerState.PENDING self.state = self._state self._error: BaseException | None = None @@ -333,6 +336,8 @@ async def _run_async(self) -> ResultType: elif inspect.isawaitable(self._work): return await self._work elif callable(self._work): + if not self._thread_worker: + return self._work() raise WorkerError("Request to run a non-async function as an async worker") raise WorkerError("Unsupported attempt to run an async worker") From 093aeddc2a6d042a6c542cc231202fe1aa5b0cd9 Mon Sep 17 00:00:00 2001 From: pmp-p Date: Sun, 26 Nov 2023 09:35:55 +0100 Subject: [PATCH 2/3] scrolling ok, remove unneeded changes --- src/textual/app.py | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/textual/app.py b/src/textual/app.py index bc6a2ac4c9..c2b62dd5a2 100644 --- a/src/textual/app.py +++ b/src/textual/app.py @@ -96,7 +96,12 @@ from .notifications import Notification, Notifications, Notify, SeverityLevel from .reactive import Reactive from .renderables.blank import Blank -from .screen import Screen, ScreenResultCallbackType, ScreenResultType +from .screen import ( + Screen, + ScreenResultCallbackType, + ScreenResultType, + _SystemModalScreen, +) from .widget import AwaitMount, Widget from .widgets._toast import ToastRack from .worker import NoActiveWorker, get_current_worker @@ -474,6 +479,7 @@ def __init__( self.stylesheet = Stylesheet(variables=self.get_css_variables()) css_path = css_path or self.CSS_PATH + css_paths = [] try: css_paths.append(_make_path_object_relative(css_path, self)) @@ -486,6 +492,7 @@ def __init__( css_path.append([]) self.css_path = css_paths + self._registry: WeakSet[DOMNode] = WeakSet() # Sensitivity on X is double the sensitivity on Y to account for @@ -604,8 +611,14 @@ def children(self) -> Sequence["Widget"]: A sequence of widgets. """ try: - return (self.screen,) - except ScreenError: + return ( + next( + screen + for screen in reversed(self._screen_stack) + if not isinstance(screen, _SystemModalScreen) + ), + ) + except StopIteration: return () @contextmanager @@ -1136,7 +1149,7 @@ async def _press_keys(self, keys: Iterable[str]) -> None: for key in keys: if key.startswith("wait:"): _, wait_ms = key.split(":") - #print(f"(pause {wait_ms}ms)") + print(f"(pause {wait_ms}ms)") await asyncio.sleep(float(wait_ms) / 1000) else: if len(key) == 1 and not key.isalnum(): @@ -1147,7 +1160,7 @@ async def _press_keys(self, keys: Iterable[str]) -> None: char = unicodedata.lookup(_get_unicode_name_from_key(original_key)) except KeyError: char = key if len(key) == 1 else None - #print(f"press {key!r} (char={char!r})") + print(f"press {key!r} (char={char!r})") key_event = events.Key(key, char) key_event._set_sender(app) driver.send_event(key_event) @@ -2195,6 +2208,7 @@ async def invoke_ready_callback() -> None: self.check_idle() finally: self._mounted_event.set() + self._is_mounted = True Reactive._initialize_object(self) From e5d8be1b9fb39eed7aec10b5ddfe9c2dcadab785 Mon Sep 17 00:00:00 2001 From: pmp-p Date: Sun, 3 Dec 2023 16:53:54 +0100 Subject: [PATCH 3/3] fix no css --- src/textual/app.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/textual/app.py b/src/textual/app.py index c2b62dd5a2..8fa357a3f3 100644 --- a/src/textual/app.py +++ b/src/textual/app.py @@ -479,7 +479,9 @@ def __init__( self.stylesheet = Stylesheet(variables=self.get_css_variables()) css_path = css_path or self.CSS_PATH - + if not css_path: + css_path = '/tmp/default.tcss' + open(css_path,'w').close() css_paths = [] try: css_paths.append(_make_path_object_relative(css_path, self))