diff --git a/spyder/plugins/ipythonconsole/__init__.py b/spyder/plugins/ipythonconsole/__init__.py index 2ff34ccd29d..de5cf9b96d7 100644 --- a/spyder/plugins/ipythonconsole/__init__.py +++ b/spyder/plugins/ipythonconsole/__init__.py @@ -44,5 +44,12 @@ class SpyderKernelError(RuntimeError): - """Error to be shown in client.""" - pass + """ + Error to be shown in the IPython console. + + Notes + ----- + * Use this exception if you want to show a nice formatted error in the + current console instead of a long and hard-to-read traceback. + * This should only be used for errors whose cause we are certain of. + """ diff --git a/spyder/plugins/ipythonconsole/utils/client.py b/spyder/plugins/ipythonconsole/utils/client.py index 7f10a69bc5d..57fa71e2bf7 100644 --- a/spyder/plugins/ipythonconsole/utils/client.py +++ b/spyder/plugins/ipythonconsole/utils/client.py @@ -20,6 +20,7 @@ # Local imports from spyder.api.asyncdispatcher import AsyncDispatcher from spyder.api.translations import _ +from spyder.plugins.ipythonconsole import SpyderKernelError class KernelClientTunneler: @@ -63,10 +64,10 @@ async def forward_port(self, remote_host, remote_port): ) ) except asyncssh.Error as err: - raise RuntimeError( + raise SpyderKernelError( _( - "It was not possible to open an SSH tunnel for the " - "remote kernel. Please check your credentials and the " + "It was not possible to open an SSH tunnel to connect to " + "the remote kernel. Please check your credentials and the " "server connection status." ) ) from err diff --git a/spyder/plugins/ipythonconsole/utils/kernel_handler.py b/spyder/plugins/ipythonconsole/utils/kernel_handler.py index 10dada739d9..b8a9f73f305 100644 --- a/spyder/plugins/ipythonconsole/utils/kernel_handler.py +++ b/spyder/plugins/ipythonconsole/utils/kernel_handler.py @@ -27,6 +27,7 @@ SPYDER_KERNELS_VERSION, SPYDER_KERNELS_CONDA, SPYDER_KERNELS_PIP, + SpyderKernelError, ) from spyder.plugins.ipythonconsole.comms.kernelcomm import KernelComm from spyder.plugins.ipythonconsole.utils.manager import SpyderKernelManager @@ -35,8 +36,8 @@ PERMISSION_ERROR_MSG = _( - "The directory {} is not writable and it is required to create IPython " - "consoles. Please make it writable." + "The directory {} is not writable and it is required to create " + "IPython consoles. Please make it writable." ) ERROR_SPYDER_KERNEL_VERSION = _( @@ -377,7 +378,7 @@ def new_from_spec(cls, kernel_spec): """ connection_file = cls.new_connection_file() if connection_file is None: - raise RuntimeError( + raise SpyderKernelError( PERMISSION_ERROR_MSG.format(jupyter_runtime_dir()) ) @@ -390,11 +391,19 @@ def new_from_spec(cls, kernel_spec): kernel_manager._kernel_spec = kernel_spec - kernel_manager.start_kernel( - stderr=PIPE, - stdout=PIPE, - env=kernel_spec.env, - ) + try: + kernel_manager.start_kernel( + stderr=PIPE, + stdout=PIPE, + env=kernel_spec.env, + ) + except PermissionError: + # Show a nice error message when jupyter_runtime_dir is not + # writable. + # Fixes spyder-ide/spyder#23124 + raise SpyderKernelError( + PERMISSION_ERROR_MSG.format(jupyter_runtime_dir()) + ) # Kernel client kernel_client = kernel_manager.client() @@ -474,13 +483,13 @@ def init_kernel_client( try: kernel_client.load_connection_file() except Exception as e: - raise RuntimeError( + raise SpyderKernelError( _( "An error occurred while trying to load " "the kernel connection file. The error " "was:\n\n" ) - + str(e) + + f"{str(e)}" ) if hostname is not None or ssh_connection is not None: