Skip to content

Commit

Permalink
Kernel: Simplify the way we get the Matplotlib interactive backend
Browse files Browse the repository at this point in the history
- It seems the current way broke in one of the recent IPykernel
updates.
- Also, make a small fix to correctly report the Inline backend after
enabling it in IPython 8.24.
  • Loading branch information
ccordoba12 committed May 4, 2024
1 parent bf782e0 commit 2bc4687
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 34 deletions.
46 changes: 13 additions & 33 deletions spyder_kernels/console/kernel.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
15 changes: 14 additions & 1 deletion spyder_kernels/console/shell.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,14 +87,27 @@ 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(
blocking=False
).update_matplotlib_gui(gui)
except Exception:
pass

return gui, backend

# --- For Pdb namespace integration
Expand Down

0 comments on commit 2bc4687

Please sign in to comment.