diff --git a/taipy/gui/_default_config.py b/taipy/gui/_default_config.py index 4cc540ea4..7cbc6f20a 100644 --- a/taipy/gui/_default_config.py +++ b/taipy/gui/_default_config.py @@ -46,7 +46,7 @@ "change_delay": None, "chart_dark_template": None, "base_url": "/", - "client_url": "http://localhost:5000", + "client_url": "http://localhost:{port}", "dark_mode": True, "dark_theme": None, "debug": False, diff --git a/taipy/gui/_gui_cli.py b/taipy/gui/_gui_cli.py index 3a23e5bda..011f97e54 100644 --- a/taipy/gui/_gui_cli.py +++ b/taipy/gui/_gui_cli.py @@ -35,6 +35,14 @@ class _GuiCLI(_AbstractCLI): "const": "", "help": "Specify server host", }, + ("--client-url", "-H"): { + "dest": "taipy_client_url", + "metavar": "CLIENT_URL", + "nargs": "?", + "default": "", + "const": "", + "help": "Specify client url", + }, ("--ngrok-token",): { "dest": "taipy_ngrok_token", "metavar": "NGROK_TOKEN", diff --git a/taipy/gui/config.py b/taipy/gui/config.py index 810b650b7..d30c6c30a 100644 --- a/taipy/gui/config.py +++ b/taipy/gui/config.py @@ -223,6 +223,8 @@ def _handle_argparse(self): config["upload_folder"] = args.taipy_upload_folder elif os.environ.get("TAIPY_GUI_UPLOAD_FOLDER"): config["webapp_path"] = os.environ.get("TAIPY_GUI_UPLOAD_FOLDER") + if args.taipy_client_url: + config["client_url"] = args.taipy_client_url def _build_config(self, root_dir, env_filename, kwargs): # pragma: no cover config = self.config diff --git a/taipy/gui/gui.py b/taipy/gui/gui.py index b9e365d54..1fc7db45a 100644 --- a/taipy/gui/gui.py +++ b/taipy/gui/gui.py @@ -2427,6 +2427,9 @@ def get_flask_app(self) -> Flask: return t.cast(Flask, self._server.get_flask()) raise RuntimeError("get_flask_app() cannot be invoked before run() has been called.") + def _get_port(self) -> int: + return self._server.get_port() + def _set_frame(self, frame: t.Optional[FrameType]): if not isinstance(frame, FrameType): # pragma: no cover raise RuntimeError("frame must be a FrameType where Gui can collect the local variables.") @@ -2624,6 +2627,8 @@ def __register_blueprint(self): # server URL Rule for flask rendered react-router pages_bp.add_url_rule(f"/{Gui.__INIT_URL}", view_func=self.__init_route) + _Hooks()._add_external_blueprint(self, __name__) + # Register Flask Blueprint if available for bp in self._flask_blueprint: t.cast(Flask, self._server.get_flask()).register_blueprint(bp) @@ -2790,6 +2795,7 @@ def run( return self._server.run( host=app_config.get("host"), port=app_config.get("port"), + client_url=app_config.get("client_url"), debug=app_config.get("debug"), use_reloader=app_config.get("use_reloader"), flask_log=app_config.get("flask_log"), diff --git a/taipy/gui/server.py b/taipy/gui/server.py index dfada6091..700dac194 100644 --- a/taipy/gui/server.py +++ b/taipy/gui/server.py @@ -246,6 +246,9 @@ def _direct_render_json(self, data): def get_flask(self): return self._flask + def get_port(self): + return self._port + def test_client(self): return t.cast(Flask, self._flask).test_client() @@ -286,6 +289,7 @@ def run( self, host, port, + client_url, debug, use_reloader, flask_log, @@ -299,6 +303,7 @@ def run( if port == "auto": port = self._get_random_port(port_auto_ranges) self._port = port + client_url = client_url.format(port=port) if _is_in_notebook() and notebook_proxy: # pragma: no cover from .utils.proxy import NotebookProxy @@ -320,8 +325,9 @@ def run( _TaipyLogger._get_logger().info(f" * Server starting on http://{host_value}:{port}") else: _TaipyLogger._get_logger().info(f" * Server reloaded on http://{host_value}:{port}") + _TaipyLogger._get_logger().info(f" * Application is accessible at {client_url}") if not is_running_from_reloader() and self._gui._get_config("run_browser", False): - webbrowser.open(f"http://{host_value}{f':{port}' if port else ''}", new=2) + webbrowser.open(client_url, new=2) if _is_in_notebook() or run_in_thread: self._thread = KThread(target=self._run_notebook) self._thread.start() diff --git a/tests/gui/helpers.py b/tests/gui/helpers.py index 96ec5be70..634fb6cfd 100644 --- a/tests/gui/helpers.py +++ b/tests/gui/helpers.py @@ -151,6 +151,7 @@ def run_e2e_multi_client(gui: Gui): gui._server.run( host=gui._get_config("host", "127.0.0.1"), port=gui._get_config("port", 5000), + client_url=gui._get_config("client_url", "http://localhost:{port}"), debug=False, use_reloader=False, flask_log=False,