浏览代码

Merge branch 'main' into #61-page-decorator

# Conflicts:
#	nicegui/globals.py
Falko Schindler 2 年之前
父节点
当前提交
392732e664
共有 4 个文件被更改,包括 41 次插入7 次删除
  1. 3 0
      nicegui/globals.py
  2. 15 5
      nicegui/lifecycle.py
  3. 22 1
      nicegui/run.py
  4. 1 1
      nicegui/ui.py

+ 3 - 0
nicegui/globals.py

@@ -4,6 +4,8 @@ import asyncio
 import logging
 from typing import TYPE_CHECKING, Awaitable, Callable, Dict, List, Union
 
+from uvicorn import Server
+
 if TYPE_CHECKING:
     import justpy as jp
     from starlette.applications import Starlette
@@ -13,6 +15,7 @@ if TYPE_CHECKING:
 
 app: 'Starlette'
 config: 'Config'
+server: Server
 page_builders: Dict[str, 'PageBuilder'] = {}
 view_stack: List['jp.HTMLBaseComponent'] = []
 tasks: List[asyncio.tasks.Task] = []

+ 15 - 5
nicegui/lifecycle.py

@@ -1,19 +1,29 @@
 from typing import Awaitable, Callable, Union
 
-from .globals import connect_handlers, disconnect_handlers, shutdown_handlers, startup_handlers
+import justpy as jp
+
+from . import globals
 
 
 def on_connect(self, handler: Union[Callable, Awaitable]):
-    connect_handlers.append(handler)
+    globals.connect_handlers.append(handler)
 
 
 def on_disconnect(self, handler: Union[Callable, Awaitable]):
-    disconnect_handlers.append(handler)
+    globals.disconnect_handlers.append(handler)
 
 
 def on_startup(self, handler: Union[Callable, Awaitable]):
-    startup_handlers.append(handler)
+    globals.startup_handlers.append(handler)
 
 
 def on_shutdown(self, handler: Union[Callable, Awaitable]):
-    shutdown_handlers.append(handler)
+    globals.shutdown_handlers.append(handler)
+
+
+async def shutdown(self) -> None:
+    if globals.config.reload:
+        raise Exception('ui.shutdown is not supported when auto-reload is enabled')
+    for socket in [s for page in jp.WebPage.sockets.values() for s in page.values()]:
+        await socket.close()
+    globals.server.should_exit = True

+ 22 - 1
nicegui/run.py

@@ -6,6 +6,8 @@ import webbrowser
 from typing import List, Optional
 
 import uvicorn
+from uvicorn.main import STARTUP_FAILURE
+from uvicorn.supervisors import ChangeReload, Multiprocess
 
 from . import globals
 from .config import Config
@@ -18,7 +20,7 @@ def _start_server(config: Config) -> None:
     def split_args(args: str) -> List[str]:
         return args.split(',') if ',' in args else [args]
 
-    uvicorn.run(
+    config = uvicorn.Config(
         'nicegui:app' if config.reload else globals.app,
         host=config.host,
         port=config.port,
@@ -29,6 +31,25 @@ def _start_server(config: Config) -> None:
         reload_dirs=split_args(config.uvicorn_reload_dirs) if config.reload else None,
         log_level=config.uvicorn_logging_level,
     )
+    globals.server = uvicorn.Server(config=config)
+
+    if (config.reload or config.workers > 1) and not isinstance(config.app, str):
+        logging.warning('You must pass the application as an import string to enable "reload" or "workers".')
+        sys.exit(1)
+
+    if config.should_reload:
+        sock = config.bind_socket()
+        ChangeReload(config, target=globals.server.run, sockets=[sock]).run()
+    elif config.workers > 1:
+        sock = config.bind_socket()
+        Multiprocess(config, target=globals.server.run, sockets=[sock]).run()
+    else:
+        globals.server.run()
+    if config.uds:
+        os.remove(config.uds)  # pragma: py-win32
+
+    if not globals.server.started and not config.should_reload and config.workers == 1:
+        sys.exit(STARTUP_FAILURE)
 
 
 if globals.pre_evaluation_succeeded and globals.config.reload and not inspect.stack()[-2].filename.endswith('spawn.py'):

+ 1 - 1
nicegui/ui.py

@@ -44,7 +44,7 @@ class Ui:
     from .elements.tree import Tree as tree
     from .elements.update import update
     from .elements.upload import Upload as upload
-    from .lifecycle import on_connect, on_disconnect, on_shutdown, on_startup
+    from .lifecycle import on_connect, on_disconnect, on_shutdown, on_startup, shutdown
     from .routes import add_route, add_static_files, get
     from .timer import Timer as timer