瀏覽代碼

Introducing PageEvent and updated docs/tests #130

Rodja Trappe 2 年之前
父節點
當前提交
d2f066a4c0
共有 4 個文件被更改,包括 35 次插入14 次删除
  1. 15 7
      api_docs_and_examples.py
  2. 1 0
      nicegui/events.py
  3. 9 3
      nicegui/page.py
  4. 10 4
      tests/test_pages.py

+ 15 - 7
api_docs_and_examples.py

@@ -643,20 +643,28 @@ If the page function expects a `request` argument, the request object is automat
 
     yield_page_ready = '''#### Yielding for Page-Ready
 
-This is a handy alternative to the `on_page_ready` callback (either as parameter of `@ui.page` or via `ui.on_page_ready` function).
+This is a handy alternative to the `on_page_ready` callback of the `@ui.page` decorator.
 
 If a `yield` statement is provided in a page builder function, all code below that statement is executed after the page is ready.
 This allows you to execute JavaScript; which is only possible after the page has been loaded (see [#112](https://github.com/zauberzeug/nicegui/issues/112)).
-Also it is possible to do async stuff while the user already sees the content added before the yield statement.
+Also it is possible to do async stuff while the user already sees the content which was added before the yield statement.
+
+The yield statement returns `nicegui.events.PageEvent`. 
+This contains the websocket of the client.
     '''
     with example(yield_page_ready):
+        from typing import Generator
+
+        from nicegui.events import PageEvent
+
         @ui.page('/yield_page_ready')
-        async def yield_page_ready():
+        async def yield_page_ready() -> Generator[None, PageEvent, None]:
             ui.label('This text is displayed immediately.')
-            yield
-            ui.run_javascript('document.title = "JavaScript-Controlled Title")')
-            await asyncio.sleep(3)
-            ui.label('This text is displayed 3 seconds after the page has been fully loaded.')
+            page_ready = yield
+            await ui.run_javascript('document.title = "JavaScript-Controlled Title")')
+            await asyncio.sleep(2)
+            ui.label('This text is displayed 2 seconds after the page has been fully loaded.')
+            ui.label(f'The IP address {page_ready.socket.client.host} could be obtained from the websocket.')
 
         ui.link('show page-ready code after yield', '/yield_page_ready')
 

+ 1 - 0
nicegui/events.py

@@ -9,6 +9,7 @@ from . import globals
 from .elements.element import Element
 from .helpers import is_coroutine
 from .lifecycle import on_startup
+from .page import PageEvent
 from .task_logger import create_task
 
 

+ 9 - 3
nicegui/page.py

@@ -5,6 +5,7 @@ import inspect
 import time
 import types
 import uuid
+from dataclasses import dataclass
 from functools import wraps
 from typing import Callable, Dict, Generator, List, Optional
 
@@ -22,6 +23,11 @@ from .page_builder import PageBuilder
 from .routes import add_route, convert_arguments
 
 
+@dataclass
+class PageEvent:
+    socket: WebSocket
+
+
 class Page(jp.QuasarPage):
 
     def __init__(self,
@@ -50,7 +56,7 @@ class Page(jp.QuasarPage):
         self.css = css
         self.connect_handler = on_connect
         self.page_ready_handler = on_page_ready
-        self.page_ready_generator: Optional[Generator[None, None, None]] = None
+        self.page_ready_generator: Optional[Generator[None, PageEvent, None]] = None
         self.disconnect_handler = on_disconnect
         self.shared = shared
         self.delete_flag = not shared
@@ -89,9 +95,9 @@ class Page(jp.QuasarPage):
         with globals.within_view(self.view):
             if self.page_ready_generator is not None:
                 if isinstance(self.page_ready_generator, types.AsyncGeneratorType):
-                    await self.page_ready_generator.asend(msg.websocket)
+                    await self.page_ready_generator.asend(PageEvent(msg.websocket))
                 elif isinstance(self.page_ready_generator, types.GeneratorType):
-                    self.page_ready_generator.send(msg.websocket)
+                    self.page_ready_generator.send(PageEvent(msg.websocket))
             if self.page_ready_handler:
                 arg_count = len(inspect.signature(self.page_ready_handler).parameters)
                 is_coro = is_coroutine(self.page_ready_handler)

+ 10 - 4
tests/test_pages.py

@@ -1,9 +1,11 @@
 import asyncio
 from time import time
+from typing import Generator
 from uuid import uuid4
 
 import justpy.htmlcomponents
 from nicegui import task_logger, ui
+from nicegui.events import PageEvent
 from starlette.requests import Request
 
 from .screen import Screen
@@ -191,29 +193,33 @@ def test_adding_elements_in_on_page_ready_event(screen: Screen):
 
 def test_pageready_after_yield_on_async_page(screen: Screen):
     @ui.page('/')
-    async def page():
+    async def page() -> Generator[None, PageEvent, None]:
         ui.label('before')
-        yield
+        page_ready = yield
         await asyncio.sleep(1)
         ui.label('after')
+        ui.label(page_ready.socket.base_url)
 
     screen.open('/')
     screen.should_contain('before')
     screen.should_not_contain('after')
     screen.wait(1)
     screen.should_contain('after')
+    screen.should_contain('ws://localhost:3392/')
 
 
 def test_pageready_after_yield_on_non_async_page(screen: Screen):
     @ui.page('/')
-    def page():
+    def page() -> Generator[None, PageEvent, None]:
         t = time()
-        yield
+        page_ready = yield
         ui.label(f'loading page took {time() - t:.2f} seconds')
+        ui.label(page_ready.socket.base_url)
 
     screen.open('/')
     timing = screen.find('loading page took')
     assert 0 < float(timing.text.split()[-2]) < 3
+    screen.should_contain('ws://localhost:3392/')
 
 
 def test_pageready_after_yield_on_shared_page_raises_exception(screen: Screen):