diff --git a/requirements/posix.txt b/requirements/posix.txt index 283a8212..47512773 100644 --- a/requirements/posix.txt +++ b/requirements/posix.txt @@ -1,5 +1,5 @@ cloudpickle -ipykernel>=6.15.3,<7 +ipykernel>=6.16.1,<7 ipython>=7.31.1,<8 jupyter_client>=7.3.4,<8 pyzmq>=22.1.0 diff --git a/requirements/windows.txt b/requirements/windows.txt index 3d90d14b..4c4072bb 100644 --- a/requirements/windows.txt +++ b/requirements/windows.txt @@ -1,5 +1,5 @@ cloudpickle -ipykernel>=6.15.3,<7 +ipykernel>=6.16.1,<7 ipython>=7.31.1,<8 jupyter_client>=7.3.4,<8 pyzmq>=22.1.0 diff --git a/setup.py b/setup.py index 4eacd6da..545af893 100644 --- a/setup.py +++ b/setup.py @@ -40,7 +40,7 @@ def get_version(module='spyder_kernels'): 'backports.functools-lru-cache; python_version<"3"', 'cloudpickle', 'ipykernel<5; python_version<"3"', - 'ipykernel>=6.15.3,<7; python_version>="3"', + 'ipykernel>=6.16.1,<7; python_version>="3"', 'ipython<6; python_version<"3"', 'ipython>=7.31.1,<8; python_version>="3"', 'jupyter-client>=5.3.4,<6; python_version<"3"', diff --git a/spyder_kernels/console/kernel.py b/spyder_kernels/console/kernel.py index bd1c2431..6aba2210 100644 --- a/spyder_kernels/console/kernel.py +++ b/spyder_kernels/console/kernel.py @@ -20,6 +20,7 @@ # Third-party imports import ipykernel from ipykernel.ipkernel import IPythonKernel +from ipykernel import eventloops from traitlets.config.loader import LazyConfigValue # Local imports @@ -398,48 +399,43 @@ def get_mpl_interactive_backend(self): """ # Mapping from frameworks to backend names. mapping = { - 'qt': 'QtAgg', # For Matplotlib 3.5+ - 'qt5': 'Qt5Agg', + 'qt': 'QtAgg', 'tk': 'TkAgg', 'macosx': 'MacOSX' } - try: - # --- Get interactive framework - framework = None - - # This is necessary because _get_running_interactive_framework - # can't detect Tk in a Jupyter kernel. - if hasattr(self, 'app_wrapper'): - if hasattr(self.app_wrapper, 'app'): - import tkinter - if isinstance(self.app_wrapper.app, tkinter.Tk): - framework = 'tk' - - if framework is None: - try: - # This is necessary for Matplotlib 3.3.0+ - from matplotlib import cbook - framework = cbook._get_running_interactive_framework() - except AttributeError: - # For older versions - from matplotlib import backends - framework = backends._get_running_interactive_framework() - - # --- 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. - return 0 - elif framework in mapping: - return MPL_BACKENDS_TO_SPYDER[mapping[framework]] + # --- 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). + from IPython.core.getipython import get_ipython + loop_func = get_ipython().kernel.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: - # This covers the case of other backends (e.g. Wx or Gtk) - # which users can set interactively with the %matplotlib - # magic but not through our Preferences. - return -1 - except Exception: - return None + # Spyder doesn't handle other backends + framework = 'other' + + # --- 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. + return 0 + elif framework in mapping: + return MPL_BACKENDS_TO_SPYDER[mapping[framework]] + else: + # This covers the case of other backends (e.g. Wx or Gtk) + # which users can set interactively with the %matplotlib + # magic but not through our Preferences. + return -1 def set_matplotlib_backend(self, backend, pylab=False): """Set matplotlib backend given a Spyder backend option."""