From 402ed6347b2b8ce3b5c478a4be7f5949bd3569ce Mon Sep 17 00:00:00 2001 From: Quentin Peter Date: Mon, 22 Aug 2022 11:43:57 +0200 Subject: [PATCH] Add check of installed spyder-kernels --- spyder/plugins/ipythonconsole/__init__.py | 14 ++++++ .../ipythonconsole/utils/kernelspec.py | 43 ++++++++++++++++++- .../ipythonconsole/widgets/__init__.py | 1 + .../ipythonconsole/widgets/main_widget.py | 5 +++ .../plugins/ipythonconsole/widgets/shell.py | 28 ++++-------- 5 files changed, 71 insertions(+), 20 deletions(-) diff --git a/spyder/plugins/ipythonconsole/__init__.py b/spyder/plugins/ipythonconsole/__init__.py index 05d0531b179..fc07f5d584d 100644 --- a/spyder/plugins/ipythonconsole/__init__.py +++ b/spyder/plugins/ipythonconsole/__init__.py @@ -10,3 +10,17 @@ IPython Console plugin based on QtConsole """ +# Required version of Spyder-kernels +SPYDER_KERNELS_MIN_VERSION = '2.3.0' +SPYDER_KERNELS_MAX_VERSION = '2.4.0' +SPYDER_KERNELS_VERSION = ( + f'>={SPYDER_KERNELS_MIN_VERSION};<{SPYDER_KERNELS_MAX_VERSION}') +SPYDER_KERNELS_CONDA = ( + f'conda install spyder-kernels={SPYDER_KERNELS_MIN_VERSION[:-2]}') +SPYDER_KERNELS_PIP = ( + f'pip install spyder-kernels=={SPYDER_KERNELS_MIN_VERSION[:-1]}*') + + +class SpyderKernelError(RuntimeError): + """Error to be shown in client.""" + pass diff --git a/spyder/plugins/ipythonconsole/utils/kernelspec.py b/spyder/plugins/ipythonconsole/utils/kernelspec.py index 0acdce9a983..b9eab92b861 100644 --- a/spyder/plugins/ipythonconsole/utils/kernelspec.py +++ b/spyder/plugins/ipythonconsole/utils/kernelspec.py @@ -19,18 +19,43 @@ # Local imports from spyder.api.config.mixins import SpyderConfigurationAccessor +from spyder.api.translations import get_translation from spyder.config.base import (get_safe_mode, is_pynsist, running_in_mac_app, running_under_pytest) +from spyder.plugins.ipythonconsole import ( + SPYDER_KERNELS_CONDA, SPYDER_KERNELS_PIP, SpyderKernelError) from spyder.utils.conda import (add_quotes, get_conda_activation_script, get_conda_env_path, is_conda_env) from spyder.utils.environ import clean_env from spyder.utils.misc import get_python_executable -from spyder.utils.programs import is_python_interpreter +from spyder.utils.programs import is_python_interpreter, is_module_installed # Constants HERE = os.path.abspath(os.path.dirname(__file__)) logger = logging.getLogger(__name__) +# Localization +_ = get_translation('spyder') +ERROR_SPYDER_KERNEL_INSTALLED = _( + "The Python environment or installation whose " + "interpreter is located at" + "
"
+    "    {0}"
+    "
" + "doesn't have the spyder-kernels module " + "installed. Without this module is not possible for " + "Spyder to create a console for you.

" + "You can install it by activating your environment (if " + "necessary) and then running in a system terminal:" + "
"
+    "    {1}"
+    "
" + "or" + "
"
+    "    {2}"
+    "
" +) + def is_different_interpreter(pyexec): """Check that pyexec is a different interpreter from sys.executable.""" @@ -59,6 +84,13 @@ def get_activation_script(quote=False): return script_path +def has_spyder_kernels(pyexec): + """Check if env has spyder kernels.""" + return is_module_installed( + 'spyder_kernels', + interpreter=pyexec) + + HERE = osp.dirname(os.path.realpath(__file__)) @@ -86,6 +118,15 @@ def argv(self): pyexec = get_python_executable() else: pyexec = self.get_conf('executable', section='main_interpreter') + if not has_spyder_kernels(pyexec): + raise SpyderKernelError( + ERROR_SPYDER_KERNEL_INSTALLED.format( + pyexec, + SPYDER_KERNELS_CONDA, + SPYDER_KERNELS_PIP + ) + ) + return if not is_python_interpreter(pyexec): pyexec = get_python_executable() self.set_conf('executable', '', section='main_interpreter') diff --git a/spyder/plugins/ipythonconsole/widgets/__init__.py b/spyder/plugins/ipythonconsole/widgets/__init__.py index f6bc62a94fe..e00cc8cc059 100644 --- a/spyder/plugins/ipythonconsole/widgets/__init__.py +++ b/spyder/plugins/ipythonconsole/widgets/__init__.py @@ -19,6 +19,7 @@ from .kernelconnect import KernelConnectionDialog from .restartdialog import ConsoleRestartDialog + # ShellWidget contains the other widgets and ClientWidget # contains it from .shell import ShellWidget diff --git a/spyder/plugins/ipythonconsole/widgets/main_widget.py b/spyder/plugins/ipythonconsole/widgets/main_widget.py index 05d3dea30be..1e230a6b3cc 100644 --- a/spyder/plugins/ipythonconsole/widgets/main_widget.py +++ b/spyder/plugins/ipythonconsole/widgets/main_widget.py @@ -33,6 +33,7 @@ from spyder.api.widgets.menus import MENU_SEPARATOR from spyder.config.base import ( get_conf_path, get_home_dir, running_under_pytest) +from spyder.plugins.ipythonconsole import SpyderKernelError from spyder.plugins.ipythonconsole.utils.kernelspec import SpyderKernelSpec from spyder.plugins.ipythonconsole.utils.manager import SpyderKernelManager from spyder.plugins.ipythonconsole.utils.client import SpyderKernelClient @@ -2082,6 +2083,8 @@ def create_kernel_manager_and_kernel_client(self, connection_file, config=None, autorestart=True, ) + except SpyderKernelError as e: + return (e.args[0], None) except Exception: error_msg = _("The error is:

" "{}").format(traceback.format_exc()) @@ -2094,6 +2097,8 @@ def create_kernel_manager_and_kernel_client(self, connection_file, kernel_manager.start_kernel(stderr=stderr_handle, stdout=stdout_handle, env=kernel_spec.env) + except SpyderKernelError as e: + return (e.args[0], None) except Exception: error_msg = _("The error is:

" "{}").format(traceback.format_exc()) diff --git a/spyder/plugins/ipythonconsole/widgets/shell.py b/spyder/plugins/ipythonconsole/widgets/shell.py index ea581d0c907..93158ad1330 100644 --- a/spyder/plugins/ipythonconsole/widgets/shell.py +++ b/spyder/plugins/ipythonconsole/widgets/shell.py @@ -35,6 +35,9 @@ from spyder.plugins.ipythonconsole.utils.style import ( create_qss_style, create_style_class) from spyder.widgets.helperwidgets import MessageCheckBox +from spyder.plugins.ipythonconsole import ( + SPYDER_KERNELS_MIN_VERSION, SPYDER_KERNELS_MAX_VERSION, + SPYDER_KERNELS_VERSION, SPYDER_KERNELS_CONDA, SPYDER_KERNELS_PIP) from spyder.plugins.ipythonconsole.comms.kernelcomm import KernelComm from spyder.plugins.ipythonconsole.widgets import ( ControlWidget, DebuggingWidget, FigureBrowserWidget, HelpWidget, @@ -44,40 +47,26 @@ MODULES_FAQ_URL = ( "https://docs.spyder-ide.org/5/faq.html#using-packages-installer") -# Required version of Spyder-kernels -SPYDER_KERNELS_MIN_VERSION = '2.3.0' -SPYDER_KERNELS_MAX_VERSION = '2.4.0' -SPYDER_KERNELS_VERSION = ( - f'>={SPYDER_KERNELS_MIN_VERSION};<{SPYDER_KERNELS_MAX_VERSION}') -SPYDER_KERNELS_VERSION_MSG = _( - '>= {0} and < {1}').format( - SPYDER_KERNELS_MIN_VERSION, SPYDER_KERNELS_MAX_VERSION) -SPYDER_KERNELS_CONDA = ( - f'conda install spyder-kernels={SPYDER_KERNELS_MIN_VERSION[:-2]}') -SPYDER_KERNELS_PIP = ( - f'pip install spyder-kernels=={SPYDER_KERNELS_MIN_VERSION[:-1]}*') - ERROR_SPYDER_KERNEL_VERSION = _( "The Python environment or installation whose interpreter is located at" "
"
     "    {0}"
     "
" "doesn't have the right version of spyder-kernels installed ({1} " - "instead of {2}). Without this module is not possible for Spyder to " - "create a console for you.

" + "instead of >= {2} and < {3}). Without this module is not possible for " + "Spyder to create a console for you.

" "You can install it by activating your environment (if necessary) and " "then running in a system terminal:" "
"
-    "    {3}"
+    "    {4}"
     "
" "or" "
"
-    "    {4}"
+    "    {5}"
     "
" ) - class ShellWidget(NamepaceBrowserWidget, HelpWidget, DebuggingWidget, FigureBrowserWidget): """ @@ -379,7 +368,8 @@ def check_spyder_kernel_callback(self, reply): ERROR_SPYDER_KERNEL_VERSION.format( pyexec, version, - SPYDER_KERNELS_VERSION_MSG, + SPYDER_KERNELS_MIN_VERSION, + SPYDER_KERNELS_MAX_VERSION, SPYDER_KERNELS_CONDA, SPYDER_KERNELS_PIP )