dinhlongviolin1 пре 1 месец
родитељ
комит
d144eb8219
1 измењених фајлова са 30 додато и 6 уклоњено
  1. 30 6
      taipy/gui/servers/fastapi/server.py

+ 30 - 6
taipy/gui/servers/fastapi/server.py

@@ -11,6 +11,8 @@
 
 import os
 import pathlib
+import threading
+import time
 import typing as t
 import webbrowser
 from contextlib import contextmanager
@@ -31,6 +33,7 @@ from taipy.common.logger._taipy_logger import _TaipyLogger
 from ..._renderers.json import _TaipyJsonEncoder
 from ...config import ServerConfig
 from ...custom._page import _ExternalResourceHandlerManager
+from ...utils import _is_in_notebook, _is_port_open, _RuntimeManager
 from ..server import _Server
 from .request import request as request_context
 from .request import request_meta
@@ -264,7 +267,7 @@ class FastAPIServer(_Server):
         return self._port or -1
 
     def send_ws_message(self, *args, **kwargs):
-        if isinstance(kwargs["to"], str):
+        if isinstance(kwargs["to"], str) or kwargs["to"] is None:
             kwargs["to"] = [kwargs["to"]]
         for sid in kwargs["to"]:
             temp_kwargs = kwargs.copy()
@@ -292,8 +295,17 @@ class FastAPIServer(_Server):
             port = self._get_random_port(port_auto_ranges)
         server_url = f"http://{host_value}:{port}"
         self._port = port
+        if _is_in_notebook() or run_in_thread:
+            runtime_manager = _RuntimeManager()
+            runtime_manager.add_gui(self._gui, port)
+        if debug and not is_running_from_reloader() and _is_port_open(host_value, port):
+            raise ConnectionError(
+                f"Port {port} is already opened on {host} because another application is running on the same port.\nPlease pick another port number and rerun with the 'port=<new_port>' setting.\nYou can also let Taipy choose a port number for you by running with the 'port=\"auto\"' setting."  # noqa: E501
+            )
         if not is_running_from_reloader() and self._gui._get_config("run_browser", False):  # type: ignore[attr-defined]
             webbrowser.open(client_url or server_url, new=2)
+        if _is_in_notebook() or run_in_thread:
+            return self._run_notebook()
         self._is_running = True
         run_config = {
             "app": self._server,
@@ -301,13 +313,25 @@ class FastAPIServer(_Server):
             "port": port,
             "reload": use_reloader,
         }
-        try:
-            uvicorn.run(**run_config)
-        except KeyboardInterrupt:
-            pass
+        uvicorn.run(**run_config)
+
+    def _run_notebook(self):
+        if not self._port or not self._host:
+            raise RuntimeError("Port and host must be set before running the server in notebook mode.")
+        self._is_running = True
+        config = uvicorn.Config(app=self._server, host=self._host, port=self._port, reload=False, log_level="info")
+        self._thread_server = uvicorn.Server(config)
+        self._thread = threading.Thread(target=self._thread_server.run, daemon=True)
+        self._thread.start()
+        return
 
     def is_running(self):
         return self._is_running
 
     def stop_thread(self):
-        raise NotImplementedError
+        if hasattr(self, "_thread") and self._thread.is_alive() and self._is_running:
+            self._thread_server.should_exit = True
+            self._thread.join()
+            while _is_port_open(self._host, self._port):
+                time.sleep(0.1)
+            self._is_running = False