Procházet zdrojové kódy

add automatic UI updates for async timer and event callbacks

Falko Schindler před 2 roky
rodič
revize
fada57c0ce
4 změnil soubory, kde provedl 47 přidání a 6 odebrání
  1. 3 3
      nicegui/events.py
  2. 3 3
      nicegui/timer.py
  3. 22 0
      tests/test_events.py
  4. 19 0
      tests/test_timer.py

+ 3 - 3
nicegui/events.py

@@ -6,7 +6,7 @@ from typing import TYPE_CHECKING, Any, Callable, List, Optional
 from starlette.websockets import WebSocket
 from starlette.websockets import WebSocket
 
 
 from . import globals
 from . import globals
-from .auto_context import Context
+from .auto_context import Context, update_after_await
 from .helpers import is_coroutine
 from .helpers import is_coroutine
 from .lifecycle import on_startup
 from .lifecycle import on_startup
 from .task_logger import create_task
 from .task_logger import create_task
@@ -243,8 +243,8 @@ def handle_event(handler: Optional[Callable], arguments: EventArguments) -> Opti
             result = handler() if no_arguments else handler(arguments)
             result = handler() if no_arguments else handler(arguments)
         if is_coroutine(handler):
         if is_coroutine(handler):
             async def wait_for_result():
             async def wait_for_result():
-                with Context(arguments.sender.parent_view):
-                    await result
+                with Context(arguments.sender.parent_view) as context:
+                    await update_after_await(result, context)
             if globals.loop and globals.loop.is_running():
             if globals.loop and globals.loop.is_running():
                 create_task(wait_for_result(), name=str(handler))
                 create_task(wait_for_result(), name=str(handler))
             else:
             else:

+ 3 - 3
nicegui/timer.py

@@ -7,7 +7,7 @@ from typing import Callable, List, Optional
 from starlette.websockets import WebSocket
 from starlette.websockets import WebSocket
 
 
 from . import globals
 from . import globals
-from .auto_context import Context
+from .auto_context import Context, update_after_await
 from .binding import BindableProperty
 from .binding import BindableProperty
 from .helpers import is_coroutine
 from .helpers import is_coroutine
 from .page import Page, find_parent_page, find_parent_view
 from .page import Page, find_parent_page, find_parent_view
@@ -42,10 +42,10 @@ class Timer:
 
 
         async def do_callback():
         async def do_callback():
             try:
             try:
-                with Context(self.parent_view):
+                with Context(self.parent_view) as context:
                     result = callback()
                     result = callback()
                     if is_coroutine(callback):
                     if is_coroutine(callback):
-                        await result
+                        await update_after_await(result, context)
             except Exception:
             except Exception:
                 traceback.print_exc()
                 traceback.print_exc()
 
 

+ 22 - 0
tests/test_events.py

@@ -0,0 +1,22 @@
+import asyncio
+
+from nicegui import ui
+
+from .screen import Screen
+
+
+def test_event_with_update_after_await(screen: Screen):
+    @ui.page('/')
+    def page():
+        async def update():
+            ui.label('1')
+            await asyncio.sleep(1.0)
+            ui.label('2')
+
+        ui.button('update', on_click=update)
+
+    screen.open('/')
+    screen.click('update')
+    screen.wait_for('1')
+    screen.should_not_contain('2')
+    screen.wait_for('2')

+ 19 - 0
tests/test_timer.py

@@ -1,3 +1,5 @@
+import asyncio
+
 from nicegui import ui
 from nicegui import ui
 
 
 from .screen import Screen
 from .screen import Screen
@@ -43,3 +45,20 @@ def test_timer_on_private_page(screen: Screen):
     count = counter.value
     count = counter.value
     screen.wait(0.5)
     screen.wait(0.5)
     assert counter.value == count, 'timer is not running anymore after closing the page'
     assert counter.value == count, 'timer is not running anymore after closing the page'
+
+
+def test_timer_with_update_after_await(screen: Screen):
+    @ui.page('/')
+    def page():
+        async def update():
+            ui.label('1')
+            await asyncio.sleep(1.0)
+            ui.label('2')
+
+        ui.timer(1.0, update, once=True)
+
+    screen.open('/')
+    screen.should_not_contain('1')
+    screen.wait_for('1')
+    screen.should_not_contain('2')
+    screen.wait_for('2')