From ba40e20d778b98814590cdf1d622efc3fb403457 Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Sun, 8 Dec 2024 14:01:48 -0500 Subject: [PATCH 1/3] Remote client: Report connection status where it was missing --- spyder/plugins/remoteclient/api/client.py | 54 ++++++++++++++++++++--- 1 file changed, 48 insertions(+), 6 deletions(-) diff --git a/spyder/plugins/remoteclient/api/client.py b/spyder/plugins/remoteclient/api/client.py index b7f577adb01..5aabeec26d5 100644 --- a/spyder/plugins/remoteclient/api/client.py +++ b/spyder/plugins/remoteclient/api/client.py @@ -330,6 +330,10 @@ async def __start_remote_server(self): """Start remote server.""" if not self.ssh_is_connected: self._logger.error("SSH connection is not open") + self.__emit_connection_status( + ConnectionStatus.Error, + _("The SSH connection is not open"), + ) return False if info := await self.get_server_info(): @@ -391,7 +395,11 @@ async def __start_remote_server(self): if info is None: self._logger.error("Faield to get server info") self.__emit_connection_status( - ConnectionStatus.Error, _("Error getting server info") + ConnectionStatus.Error, + _( + "There was an error when trying to get the remote server " + "information" + ), ) return False @@ -410,7 +418,6 @@ async def __start_remote_server(self): return True self._logger.error("Error forwarding local port.") - self.__emit_connection_status( ConnectionStatus.Error, _("It was not possible to forward the local port"), @@ -421,6 +428,10 @@ async def ensure_server_installed(self) -> bool: """Check remote server version.""" if not self.ssh_is_connected: self._logger.error("SSH connection is not open") + self.__emit_connection_status( + ConnectionStatus.Error, + _("The SSH connection is not open"), + ) return "" commnad = get_server_version_command(self.options["platform"]) @@ -435,6 +446,10 @@ async def ensure_server_installed(self) -> bool: return await self.install_remote_server() except asyncssh.TimeoutError: self._logger.error("Checking server version timed out") + self.__emit_connection_status( + ConnectionStatus.Error, + _("The server version check timed out"), + ) return False version = output.stdout.splitlines()[-1].strip() @@ -483,6 +498,10 @@ async def __install_remote_server(self): """Install remote server.""" if not self.ssh_is_connected: self._logger.error("SSH connection is not open") + self.__emit_connection_status( + ConnectionStatus.Error, + _("The SSH connection is not open"), + ) return False self._logger.debug( @@ -491,21 +510,33 @@ async def __install_remote_server(self): try: command = get_installer_command(self.options["platform"]) - except NotImplementedError as e: + except NotImplementedError: self._logger.error( f"Cannot install spyder-remote-server on " f"{self.options['platform']} automatically. Please install it " f"manually." ) + self.__emit_connection_status( + status=ConnectionStatus.Error, + message=_("There was an error installing the remote server"), + ) return False try: await self._ssh_connection.run(command, check=True) except asyncssh.ProcessError as err: - self._logger.error(f"Instalation script failed: {err.stderr}") + self._logger.error(f"Installation script failed: {err.stderr}") + self.__emit_connection_status( + status=ConnectionStatus.Error, + message=_("There was an error installing the remote server"), + ) return False except asyncssh.TimeoutError: - self._logger.error("Instalation script timed out") + self._logger.error("Installation script timed out") + self.__emit_connection_status( + status=ConnectionStatus.Error, + message=_("There was an error installing the remote server"), + ) return False self._logger.info( @@ -567,7 +598,6 @@ async def __create_new_connection(self) -> bool: ) except (OSError, asyncssh.Error) as e: self._logger.error(f"Failed to open ssh connection: {e}") - self.__emit_connection_status( ConnectionStatus.Error, _("It was not possible to open a connection to this machine"), @@ -582,10 +612,18 @@ async def forward_local_port(self): """Forward local port.""" if not self.server_port: self._logger.error("Server port is not set") + self.__emit_connection_status( + status=ConnectionStatus.Error, + message=_("The server port is not set"), + ) return False if not self.ssh_is_connected: self._logger.error("SSH connection is not open") + self.__emit_connection_status( + status=ConnectionStatus.Error, + message=_("The SSH connection is not open"), + ) return False self._logger.debug( @@ -645,6 +683,10 @@ async def stop_remote_server(self): if not self.ssh_is_connected: self._logger.error("SSH connection is not open") + self.__emit_connection_status( + ConnectionStatus.Error, + _("The SSH connection is not open"), + ) return False # bug in jupyterhub, need to send SIGINT twice From 3f8236f24ce2de399aa9a7e5c9433f3f160b854d Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Sun, 8 Dec 2024 14:32:02 -0500 Subject: [PATCH 2/3] Remote client: Improve several client messages --- spyder/plugins/remoteclient/api/client.py | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/spyder/plugins/remoteclient/api/client.py b/spyder/plugins/remoteclient/api/client.py index 5aabeec26d5..f52ed3b907a 100644 --- a/spyder/plugins/remoteclient/api/client.py +++ b/spyder/plugins/remoteclient/api/client.py @@ -171,11 +171,11 @@ def api_token(self): @property def peer_host(self): - if not self.ssh_is_connected: + if self._ssh_connection is not None: + return self._ssh_connection.get_extra_info("peername")[0] + else: return None - return self._ssh_connection.get_extra_info("peername")[0] - @property def peer_port(self): if not self.ssh_is_connected: @@ -247,7 +247,7 @@ async def get_server_info(self): info = json.loads(output.stdout.splitlines()[-1]) except (json.JSONDecodeError, IndexError): self._logger.debug( - f"Error parsing server info, received: {output.stdout}" + f"Issue parsing server info: {output.stdout}" ) return None @@ -442,7 +442,9 @@ async def ensure_server_installed(self) -> bool: ) except asyncssh.ProcessError as err: # Server is not installed - self._logger.warning(f"Error checking server version: {err.stderr}") + self._logger.warning( + f"Issue checking server version: {err.stderr}" + ) return await self.install_remote_server() except asyncssh.TimeoutError: self._logger.error("Checking server version timed out") @@ -467,9 +469,10 @@ async def ensure_server_installed(self) -> bool: return False if Version(version) < Version(SPYDER_REMOTE_MIN_VERSION): - self._logger.error( + self._logger.warning( f"Server version mismatch: {version} is lower than " - f"the minimum supported version {SPYDER_REMOTE_MIN_VERSION}" + f"the minimum supported version {SPYDER_REMOTE_MIN_VERSION}. " + f"A more recent version will be installed." ) return await self.install_remote_server() @@ -586,7 +589,7 @@ async def __create_new_connection(self) -> bool: _("We're establishing the connection. Please be patient"), ) - conect_kwargs = { + connect_kwargs = { k: v for k, v in self.options.items() if k not in self._extra_options @@ -594,7 +597,7 @@ async def __create_new_connection(self) -> bool: self._logger.debug("Opening SSH connection") try: self._ssh_connection = await asyncssh.connect( - **conect_kwargs, client_factory=self.client_factory + **connect_kwargs, client_factory=self.client_factory ) except (OSError, asyncssh.Error) as e: self._logger.error(f"Failed to open ssh connection: {e}") From 7dfa72c6452f87c9ba4d3f06524d7ff858873c51 Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Sun, 8 Dec 2024 15:53:47 -0500 Subject: [PATCH 3/3] Remote client: Separate log messages with a small vertical space --- spyder/plugins/remoteclient/widgets/connectionstatus.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/spyder/plugins/remoteclient/widgets/connectionstatus.py b/spyder/plugins/remoteclient/widgets/connectionstatus.py index 0606f032fd9..bb51aa630c9 100644 --- a/spyder/plugins/remoteclient/widgets/connectionstatus.py +++ b/spyder/plugins/remoteclient/widgets/connectionstatus.py @@ -192,7 +192,10 @@ def add_log(self, log: RemoteClientLog): self._copy_logs_button.setEnabled(True) formatted_log = ( - LOG_LEVEL_TO_FMT_STRING[log["level"]] + " " + log["message"] + # Message + f"

{LOG_LEVEL_TO_FMT_STRING[log['level']]} {log['message']}

" + # Small vertical space to separate logs + f"

" ) # Move cursor so that new logs are always shown at the end