Falko Schindler 2 anni fa
parent
commit
c1bec33557

+ 3 - 2
api_docs_and_examples.py

@@ -5,7 +5,8 @@ from typing import Callable, Union
 
 import docutils.core
 
-from nicegui import auto_context, globals, ui
+from nicegui import ui
+from nicegui.auto_context import Context
 from nicegui.task_logger import create_task
 
 REGEX_H4 = re.compile(r'<h4.*?>(.*?)</h4>')
@@ -815,7 +816,7 @@ This will make `ui.plot` and `ui.line_plot` unavailable.
             ui.notify('Turning off that line plot to save resources on our live demo server. 😎')
         line_checkbox.value = msg.value
         if msg.value:
-            with auto_context.within_view(line_checkbox.view):
+            with Context(line_checkbox.view):
                 ui.timer(10.0, turn_off, once=True)
         line_checkbox.update()
         return False

+ 9 - 5
nicegui/auto_context.py

@@ -1,9 +1,12 @@
 import asyncio
-from typing import Any, Coroutine, Generator, List
+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
@@ -22,8 +25,9 @@ def prune_view_stack() -> None:
         del globals.view_stacks[task_id]
 
 
-class within_view(object):
-    def __init__(self, view: 'jp.HTMLBaseComponent'):
+class Context:
+
+    def __init__(self, view: 'jp.HTMLBaseComponent') -> None:
         self.view = view
 
     def __enter__(self):
@@ -36,7 +40,7 @@ class within_view(object):
         prune_view_stack()
         self.lazy_update()
 
-    def lazy_update(self):
+    def lazy_update(self) -> None:
         if len(self.view) != self.child_count:
             self.child_count = len(self.view)
             create_task(self.view.update())
@@ -44,7 +48,7 @@ class within_view(object):
 
 class update_after_await:
 
-    def __init__(self, coro: Coroutine, context):
+    def __init__(self, coro: Coroutine, context: Context) -> None:
         self.coro = coro
         self.context = context
         self.context.lazy_update()

+ 3 - 3
nicegui/elements/group.py

@@ -4,7 +4,7 @@ from typing import List
 
 import justpy as jp
 
-from .. import auto_context, globals
+from ..auto_context import get_view_stack
 from ..binding import active_links, bindable_properties, bindings
 from .element import Element
 
@@ -13,11 +13,11 @@ class Group(Element):
 
     def __enter__(self):
         self._child_count_on_enter = len(self.view)
-        auto_context.get_view_stack().append(self.view)
+        get_view_stack().append(self.view)
         return self
 
     def __exit__(self, *_):
-        auto_context.get_view_stack().pop()
+        get_view_stack().pop()
         if self._child_count_on_enter != len(self.view):
             self.update()
 

+ 3 - 3
nicegui/elements/scene.py

@@ -5,7 +5,7 @@ from typing import Callable, Optional
 import websockets
 from justpy import WebPage
 
-from .. import auto_context, globals
+from ..auto_context import get_view_stack
 from ..events import handle_event
 from ..page import Page
 from ..routes import add_dependencies
@@ -111,14 +111,14 @@ class Scene(Element):
         super().__init__(SceneView(width=width, height=height, on_click=on_click))
 
     def __enter__(self):
-        auto_context.get_view_stack().append(self.view)
+        get_view_stack().append(self.view)
         scene = self.view.objects.get('scene', SceneObject(self.view, self.page))
         Object3D.stack.clear()
         Object3D.stack.append(scene)
         return self
 
     def __exit__(self, *_):
-        auto_context.get_view_stack().pop()
+        get_view_stack().pop()
 
     def move_camera(self,
                     x: Optional[float] = None,

+ 4 - 3
nicegui/events.py

@@ -5,7 +5,8 @@ from typing import TYPE_CHECKING, Any, Callable, List, Optional
 
 from starlette.websockets import WebSocket
 
-from . import auto_context, globals
+from . import globals
+from .auto_context import Context
 from .helpers import is_coroutine
 from .lifecycle import on_startup
 from .task_logger import create_task
@@ -238,11 +239,11 @@ def handle_event(handler: Optional[Callable], arguments: EventArguments) -> Opti
         if handler is None:
             return False
         no_arguments = not signature(handler).parameters
-        with auto_context.within_view(arguments.sender.parent_view):
+        with Context(arguments.sender.parent_view):
             result = handler() if no_arguments else handler(arguments)
         if is_coroutine(handler):
             async def wait_for_result():
-                with auto_context.within_view(arguments.sender.parent_view):
+                with Context(arguments.sender.parent_view):
                     await result
             if globals.loop and globals.loop.is_running():
                 create_task(wait_for_result(), name=str(handler))

+ 1 - 3
nicegui/globals.py

@@ -2,15 +2,13 @@ from __future__ import annotations
 
 import asyncio
 import logging
-from contextlib import contextmanager
 from enum import Enum
-from typing import TYPE_CHECKING, Awaitable, Callable, Dict, Generator, List, Optional, Union
+from typing import TYPE_CHECKING, Awaitable, Callable, Dict, List, Optional, Union
 
 from starlette.applications import Starlette
 from uvicorn import Server
 
 from .config import Config
-from .task_logger import create_task
 
 if TYPE_CHECKING:
     import justpy as jp

+ 8 - 7
nicegui/page.py

@@ -16,7 +16,8 @@ from starlette.responses import FileResponse
 from starlette.routing import Route, compile_path
 from starlette.websockets import WebSocket
 
-from . import auto_context, globals
+from . import globals
+from .auto_context import Context, get_view_stack, update_after_await
 from .events import PageEvent
 from .helpers import is_coroutine
 from .page_builder import PageBuilder
@@ -74,7 +75,7 @@ class Page(jp.QuasarPage):
             self.favicon = f'_favicon/{favicon}'
 
     async def _route_function(self, request: Request) -> Page:
-        with auto_context.within_view(self.view):
+        with Context(self.view):
             for handler in globals.connect_handlers + ([self.connect_handler] if self.connect_handler else []):
                 arg_count = len(inspect.signature(handler).parameters)
                 is_coro = is_coroutine(handler)
@@ -87,11 +88,11 @@ class Page(jp.QuasarPage):
         return self
 
     async def handle_page_ready(self, msg: AdDict) -> bool:
-        with auto_context.within_view(self.view) as context:
+        with Context(self.view) as context:
             try:
                 if self.page_ready_generator is not None:
                     if isinstance(self.page_ready_generator, types.AsyncGeneratorType):
-                        await auto_context.update_after_await(self.page_ready_generator.asend(PageEvent(msg.websocket)), context)
+                        await update_after_await(self.page_ready_generator.asend(PageEvent(msg.websocket)), context)
                     elif isinstance(self.page_ready_generator, types.GeneratorType):
                         self.page_ready_generator.send(PageEvent(msg.websocket))
             except (StopIteration, StopAsyncIteration):
@@ -113,7 +114,7 @@ class Page(jp.QuasarPage):
         return False
 
     async def on_disconnect(self, websocket: Optional[WebSocket] = None) -> None:
-        with auto_context.within_view(self.view):
+        with Context(self.view):
             for handler in globals.disconnect_handlers + ([self.disconnect_handler] if self.disconnect_handler else[]):
                 arg_count = len(inspect.signature(handler).parameters)
                 is_coro = is_coroutine(handler)
@@ -224,7 +225,7 @@ class page:
                 shared=self.shared,
             )
             try:
-                with auto_context.within_view(self.page.view):
+                with Context(self.page.view):
                     if 'request' in inspect.signature(func).parameters:
                         if self.shared:
                             raise RuntimeError('Cannot use `request` argument in shared page')
@@ -263,7 +264,7 @@ class page:
 
 
 def find_parent_view() -> jp.HTMLBaseComponent:
-    view_stack = auto_context.get_view_stack()
+    view_stack = get_view_stack()
     if not view_stack:
         if globals.loop and globals.loop.is_running():
             raise RuntimeError('cannot find parent view, view stack is empty')

+ 3 - 2
nicegui/timer.py

@@ -6,7 +6,8 @@ from typing import Callable, List, Optional
 
 from starlette.websockets import WebSocket
 
-from . import auto_context, globals
+from . import globals
+from .auto_context import Context
 from .binding import BindableProperty
 from .helpers import is_coroutine
 from .page import Page, find_parent_page, find_parent_view
@@ -41,7 +42,7 @@ class Timer:
 
         async def do_callback():
             try:
-                with auto_context.within_view(self.parent_view):
+                with Context(self.parent_view):
                     result = callback()
                     if is_coroutine(callback):
                         await result

+ 1 - 1
tests/screen.py

@@ -159,7 +159,7 @@ class Screen:
     def wait(self, t: float) -> None:
         time.sleep(t)
 
-    def wait_for(self, text: str, timeout=1):
+    def wait_for(self, text: str, timeout: float = 1.0) -> None:
         start = time.time()
         while not self.find(text):
             if time.time() - start > timeout: