瀏覽代碼

update auto-context

Falko Schindler 2 年之前
父節點
當前提交
450d324ef5
共有 5 個文件被更改,包括 48 次插入88 次删除
  1. 32 0
      nicegui/async_updater.py
  2. 0 76
      nicegui/auto_context.py
  3. 5 1
      nicegui/client.py
  4. 4 7
      nicegui/events.py
  5. 7 4
      nicegui/slot.py

+ 32 - 0
nicegui/async_updater.py

@@ -0,0 +1,32 @@
+from typing import TYPE_CHECKING, Any, Coroutine, Generator
+
+if TYPE_CHECKING:
+    from .client import Client
+
+
+class AsyncUpdater:
+
+    def __init__(self, coro: Coroutine, client: 'Client') -> None:
+        self.coro = coro
+        self.client = client
+
+    def __await__(self) -> Generator[Any, None, Any]:
+        coro_iter = self.coro.__await__()
+        iter_send, iter_throw = coro_iter.send, coro_iter.throw
+        send, message = iter_send, None
+        while True:
+            try:
+                signal = send(message)
+                self.lazy_update()
+            except StopIteration as err:
+                return err.value
+            else:
+                send = iter_send
+            try:
+                message = yield signal
+            except BaseException as err:
+                send, message = iter_throw, err
+
+    def lazy_update(self) -> None:
+        for slot in self.client.slot_stack:
+            slot.lazy_update()

+ 0 - 76
nicegui/auto_context.py

@@ -1,76 +0,0 @@
-from __future__ import annotations
-
-import asyncio
-from typing import TYPE_CHECKING, Any, Coroutine, Generator, List
-
-from . import globals
-from .task_logger import create_task
-
-if TYPE_CHECKING:
-    import justpy as jp
-
-
-def get_task_id() -> int:
-    return id(asyncio.current_task()) if globals.loop and globals.loop.is_running() else 0
-
-
-def get_view_stack() -> List['jp.HTMLBaseComponent']:
-    task_id = get_task_id()
-    if task_id not in globals.view_stacks:
-        globals.view_stacks[task_id] = []
-    return globals.view_stacks[task_id]
-
-
-def prune_view_stack() -> None:
-    task_id = get_task_id()
-    if not globals.view_stacks[task_id]:
-        del globals.view_stacks[task_id]
-
-
-class Context:
-
-    def __init__(self, view: 'jp.HTMLBaseComponent') -> None:
-        self.view = view
-
-    def __enter__(self):
-        self.child_count = len(self.view)
-        get_view_stack().append(self.view)
-        return self
-
-    def __exit__(self, type, value, traceback):
-        get_view_stack().pop()
-        prune_view_stack()
-        self.lazy_update()
-
-    def lazy_update(self) -> None:
-        if len(self.view) != self.child_count:
-            self.child_count = len(self.view)
-            create_task(self.view.update())
-
-    def watch_asyncs(self, coro: Coroutine) -> AutoUpdaterForAsyncs:
-        return AutoUpdaterForAsyncs(coro, self)
-
-
-class AutoUpdaterForAsyncs:
-
-    def __init__(self, coro: Coroutine, context: Context) -> None:
-        self.coro = coro
-        self.context = context
-        self.context.lazy_update()
-
-    def __await__(self) -> Generator[Any, None, Any]:
-        coro_iter = self.coro.__await__()
-        iter_send, iter_throw = coro_iter.send, coro_iter.throw
-        send, message = iter_send, None
-        while True:
-            try:
-                signal = send(message)
-                self.context.lazy_update()
-            except StopIteration as err:
-                return err.value
-            else:
-                send = iter_send
-            try:
-                message = yield signal
-            except BaseException as err:
-                send, message = iter_throw, err

+ 5 - 1
nicegui/client.py

@@ -3,11 +3,12 @@ import json
 import time
 import uuid
 from pathlib import Path
-from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Union
+from typing import TYPE_CHECKING, Any, Callable, Coroutine, Dict, List, Optional, Union
 
 from fastapi.responses import HTMLResponse
 
 from . import globals, ui, vue
+from .async_updater import AsyncUpdater
 from .element import Element
 from .favicon import get_favicon_url
 from .slot import Slot
@@ -58,6 +59,9 @@ class Client:
         self.content.__exit__()
         globals.client_stack.pop()
 
+    def watch_asyncs(self, coro: Coroutine) -> AsyncUpdater:
+        return AsyncUpdater(coro, self)
+
     def build_response(self) -> HTMLResponse:
         vue_html, vue_styles, vue_scripts = vue.generate_vue_content()
         elements = json.dumps({id: element.to_dict() for id, element in self.elements.items()})

+ 4 - 7
nicegui/events.py

@@ -4,7 +4,6 @@ from inspect import signature
 from typing import TYPE_CHECKING, Any, Callable, List, Optional
 
 from . import globals
-from .auto_context import Context
 from .client import Client
 from .helpers import is_coroutine
 from .lifecycle import on_startup
@@ -249,15 +248,13 @@ def handle_event(handler: Optional[Callable], arguments: EventArguments) -> None
         if handler is None:
             return False
         no_arguments = not signature(handler).parameters
-        # TODO: with Context(arguments.sender.parent_view)
-        result = handler() if no_arguments else handler(arguments)
+        with arguments.client:
+            result = handler() if no_arguments else handler(arguments)
         if is_coroutine(handler):
             if globals.loop and globals.loop.is_running():
                 async def wait_for_result():
-                    # TODO
-                    # with Context(arguments.sender.parent_view) as context:
-                    #     await context.watch_asyncs(result)
-                    await result
+                    with arguments.client as client:
+                        await client.watch_asyncs(result)
                 create_task(wait_for_result(), name=str(handler))
             else:
                 on_startup(None, wait_for_result())

+ 7 - 4
nicegui/slot.py

@@ -12,15 +12,18 @@ class Slot:
         self.name = name
         self.parent = parent
         self.children: List['Element'] = []
-
-        self._child_count_before_enter = 0
+        self.child_count = 0
 
     def __enter__(self):
-        self._child_count_before_enter = len(self.children)
+        self.child_count = len(self.children)
         globals.client_stack[-1].slot_stack.append(self)
         return self
 
     def __exit__(self, *_):
         globals.client_stack[-1].slot_stack.pop()
-        if len(self.children) != self._child_count_before_enter:
+        self.lazy_update()
+
+    def lazy_update(self) -> None:
+        if self.child_count != len(self.children):
+            self.child_count = len(self.children)
             self.parent.update()