diff --git a/spyder_kernels/comms/utils.py b/spyder_kernels/comms/utils.py index dc6b8c99..00332349 100644 --- a/spyder_kernels/comms/utils.py +++ b/spyder_kernels/comms/utils.py @@ -53,7 +53,13 @@ def is_benign_message(self, message): # Fixes spyder-ide/spyder-kernels#343 'DeprecationWarning', # Fixes spyder-ide/spyder-kernels#365 - 'IOStream.flush timed out' + 'IOStream.flush timed out', + # Avoid unnecessary messages from set_configuration when changing + # Matplotlib options. + "Warning: Cannot change to a different GUI toolkit", + "%pylab is deprecated", + "Populating the interactive namespace", + "\n" ] return any([msg in message for msg in benign_messages]) diff --git a/spyder_kernels/console/kernel.py b/spyder_kernels/console/kernel.py index 9c837f62..2d3d5eaa 100644 --- a/spyder_kernels/console/kernel.py +++ b/spyder_kernels/console/kernel.py @@ -23,7 +23,7 @@ # Third-party imports from ipykernel.ipkernel import IPythonKernel -from ipykernel import eventloops, get_connection_info +from ipykernel import get_connection_info from traitlets.config.loader import LazyConfigValue import zmq from zmq.utils.garbage import gc @@ -76,6 +76,9 @@ def __init__(self, *args, **kwargs): # Socket to signal shell_stream locally self.loopback_socket = None + # To track the interactive backend + self.interactive_backend = None + @property def kernel_info(self): # Used for checking correct version by spyder @@ -505,43 +508,20 @@ def get_mpl_interactive_backend(self): Get current Matplotlib interactive backend. This is different from the current backend because, for instance, the - user can set first the Qt5 backend, then the Inline one. In that case, - the current backend is Inline, but the current interactive one is Qt5, + user can set first the Qt backend, then the Inline one. In that case, + the current backend is Inline, but the current interactive one is Qt, and this backend can't be changed without a kernel restart. """ - # Mapping from frameworks to backend names. - mapping = { - 'qt': 'QtAgg', - 'tk': 'TkAgg', - 'macosx': 'MacOSX' - } - - # --- Get interactive framework - framework = None - - # Detect if there is a graphical framework running by checking the - # eventloop function attached to the kernel.eventloop attribute (see - # `ipykernel.eventloops.enable_gui` for context). - loop_func = self.eventloop - - if loop_func is not None: - if loop_func == eventloops.loop_tk: - framework = 'tk' - elif loop_func == eventloops.loop_qt5: - framework = 'qt' - elif loop_func == eventloops.loop_cocoa: - framework = 'macosx' - else: - # Spyder doesn't handle other backends - framework = 'other' + # Backends that Spyder can handle + recognized_backends = {'qt', 'tk', 'macosx'} # --- Return backend according to framework - if framework is None: - # Since no interactive backend has been set yet, this is - # equivalent to having the inline one. + if self.interactive_backend is None: + # Since no interactive backend has been set yet, this is equivalent + # to having the inline one. return 'inline' - elif framework in mapping: - return MPL_BACKENDS_TO_SPYDER[mapping[framework]] + elif self.interactive_backend in recognized_backends: + return self.interactive_backend else: # This covers the case of other backends (e.g. Wx or Gtk) # which users can set interactively with the %matplotlib diff --git a/spyder_kernels/console/shell.py b/spyder_kernels/console/shell.py index 5256bb67..48cecaf3 100644 --- a/spyder_kernels/console/shell.py +++ b/spyder_kernels/console/shell.py @@ -87,7 +87,19 @@ def enable_matplotlib(self, gui=None): """Enable matplotlib.""" if gui is None or gui.lower() == "auto": gui = automatic_backend() - gui, backend = super(SpyderShell, self).enable_matplotlib(gui) + + enabled_gui, backend = super().enable_matplotlib(gui) + + # This is necessary for IPython 8.24+, which returns None after + # enabling the Inline backend. + if enabled_gui is None and gui == "inline": + enabled_gui = "inline" + gui = enabled_gui + + # To easily track the current interactive backend + if self.kernel.interactive_backend is None: + self.kernel.interactive_backend = gui if gui != "inline" else None + if self.update_gui_frontend: try: self.kernel.frontend_call( @@ -95,6 +107,7 @@ def enable_matplotlib(self, gui=None): ).update_matplotlib_gui(gui) except Exception: pass + return gui, backend # --- For Pdb namespace integration