From 3e69ce7802558d620c75d3799b0781dc46c27c52 Mon Sep 17 00:00:00 2001 From: martinRenou Date: Tue, 9 Feb 2021 16:51:04 +0100 Subject: [PATCH] Add configure_inline_support and call it in the shell This removes a circular dependency between ipykernel and IPython. --- ipykernel/pylab/backend_inline.py | 52 ++++++++++++++++++++++++++++++- ipykernel/zmqshell.py | 9 ++++++ 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/ipykernel/pylab/backend_inline.py b/ipykernel/pylab/backend_inline.py index b4350927..f5333d51 100644 --- a/ipykernel/pylab/backend_inline.py +++ b/ipykernel/pylab/backend_inline.py @@ -13,6 +13,7 @@ from matplotlib._pylab_helpers import Gcf from IPython.core.getipython import get_ipython +from IPython.core.pylabtools import select_figure_formats from IPython.display import display from .config import InlineBackend @@ -150,13 +151,62 @@ def flush_figures(): # See https://github.com/matplotlib/matplotlib/pull/1125 FigureCanvas = FigureCanvasAgg + +def configure_inline_support(shell, backend): + """Configure an IPython shell object for matplotlib use. + + Parameters + ---------- + shell : InteractiveShell instance + + backend : matplotlib backend + """ + # If using our svg payload backend, register the post-execution + # function that will pick up the results for display. This can only be + # done with access to the real shell object. + + cfg = InlineBackend.instance(parent=shell) + cfg.shell = shell + if cfg not in shell.configurables: + shell.configurables.append(cfg) + + if backend == 'module://ipykernel.pylab.backend_inline': + shell.events.register('post_execute', flush_figures) + + # Save rcParams that will be overwrittern + shell._saved_rcParams = {} + for k in cfg.rc: + shell._saved_rcParams[k] = matplotlib.rcParams[k] + # load inline_rc + matplotlib.rcParams.update(cfg.rc) + new_backend_name = "inline" + else: + try: + shell.events.unregister('post_execute', flush_figures) + except ValueError: + pass + if hasattr(shell, '_saved_rcParams'): + matplotlib.rcParams.update(shell._saved_rcParams) + del shell._saved_rcParams + new_backend_name = "other" + + # only enable the formats once -> don't change the enabled formats (which the user may + # has changed) when getting another "%matplotlib inline" call. + # See https://github.com/ipython/ipykernel/issues/29 + cur_backend = getattr(configure_inline_support, "current_backend", "unset") + if new_backend_name != cur_backend: + # Setup the default figure format + select_figure_formats(shell, cfg.figure_formats, **cfg.print_figure_kwargs) + configure_inline_support.current_backend = new_backend_name + + def _enable_matplotlib_integration(): """Enable extra IPython matplotlib integration when we are loaded as the matplotlib backend.""" from matplotlib import get_backend ip = get_ipython() backend = get_backend() if ip and backend == 'module://%s' % __name__: - from IPython.core.pylabtools import configure_inline_support, activate_matplotlib + from IPython.core.pylabtools import activate_matplotlib try: activate_matplotlib(backend) configure_inline_support(ip, backend) diff --git a/ipykernel/zmqshell.py b/ipykernel/zmqshell.py index 1e68569d..8c9cfecc 100644 --- a/ipykernel/zmqshell.py +++ b/ipykernel/zmqshell.py @@ -597,6 +597,15 @@ def init_magics(self): self.register_magics(KernelMagics) self.magics_manager.register_alias('ed', 'edit') + def enable_matplotlib(self, gui=None): + gui, backend = super(ZMQInteractiveShell, self).enable_matplotlib(gui) + + from ipykernel.pylab.backend_inline import configure_inline_support + + configure_inline_support(self, backend) + + return gui, backend + def init_virtualenv(self): # Overridden not to do virtualenv detection, because it's probably # not appropriate in a kernel. To use a kernel in a virtualenv, install