From a7d4c74a81181b880932d9b34a5934f9c34a869e 2021-04-15 08:48:22 From: martinRenou Date: 2021-04-15 08:48:22 Subject: [PATCH] Use matplotlib-inline instead of ipykernel.pylab --- diff --git a/IPython/core/display.py b/IPython/core/display.py index bd098e7..2149e60 100644 --- a/IPython/core/display.py +++ b/IPython/core/display.py @@ -371,7 +371,7 @@ class DisplayObject(object): with gzip.open(BytesIO(data), 'rt', encoding=encoding) as fp: encoding = None data = fp.read() - + # decode data, if an encoding was specified # We only touch self.data once since # subclasses such as SVG have @data.setter methods @@ -1155,7 +1155,10 @@ class Video(DisplayObject): @skip_doctest def set_matplotlib_formats(*formats, **kwargs): - """Select figure formats for the inline backend. Optionally pass quality for JPEG. + """ + DEPRECATED + + Select figure formats for the inline backend. Optionally pass quality for JPEG. For example, this enables PNG and JPEG output with a JPEG quality of 90%:: @@ -1173,20 +1176,25 @@ def set_matplotlib_formats(*formats, **kwargs): **kwargs Keyword args will be relayed to ``figure.canvas.print_figure``. """ - from IPython.core.interactiveshell import InteractiveShell - from IPython.core.pylabtools import select_figure_formats - # build kwargs, starting with InlineBackend config - kw = {} - from ipykernel.pylab.config import InlineBackend - cfg = InlineBackend.instance() - kw.update(cfg.print_figure_kwargs) - kw.update(**kwargs) - shell = InteractiveShell.instance() - select_figure_formats(shell, formats, **kw) + warnings.warn( + "`set_matplotlib_formats` is deprecated, directly use " + "`matplotlib_inline.backend_inline.set_matplotlib_formats()`", + DeprecationWarning, + stacklevel=2, + ) + + from matplotlib_inline.backend_inline import ( + set_matplotlib_formats as set_matplotlib_formats_orig, + ) + + set_matplotlib_formats_orig(*formats, **kwargs) @skip_doctest def set_matplotlib_close(close=True): - """Set whether the inline backend closes all figures automatically or not. + """ + DEPRECATED + + Set whether the inline backend closes all figures automatically or not. By default, the inline backend used in the IPython Notebook will close all matplotlib figures automatically after each cell is run. This means that @@ -1206,6 +1214,15 @@ def set_matplotlib_close(close=True): Should all matplotlib figures be automatically closed after each cell is run? """ - from ipykernel.pylab.config import InlineBackend - cfg = InlineBackend.instance() - cfg.close_figures = close + warnings.warn( + "`set_matplotlib_close` is deprecated, directly use " + "`matplotlib_inline.backend_inline.set_matplotlib_close()`", + DeprecationWarning, + stacklevel=2, + ) + + from matplotlib_inline.backend_inline import ( + set_matplotlib_close as set_matplotlib_close_orig, + ) + + set_matplotlib_close_orig(close) diff --git a/IPython/core/interactiveshell.py b/IPython/core/interactiveshell.py index 589a3be..26d0700 100644 --- a/IPython/core/interactiveshell.py +++ b/IPython/core/interactiveshell.py @@ -3514,6 +3514,7 @@ class InteractiveShell(SingletonConfigurable): display figures inline. """ from IPython.core import pylabtools as pt + from matplotlib_inline.backend_inline import configure_inline_support gui, backend = pt.find_gui_and_backend(gui, self.pylab_gui_select) if gui != 'inline': @@ -3527,7 +3528,7 @@ class InteractiveShell(SingletonConfigurable): gui, backend = pt.find_gui_and_backend(self.pylab_gui_select) pt.activate_matplotlib(backend) - pt.configure_inline_support(self, backend) + configure_inline_support(self, backend) # Now we must activate the gui pylab wants to use, and fix %run to take # plot updates into account diff --git a/IPython/core/pylabtools.py b/IPython/core/pylabtools.py index 3af899e..2a20870 100644 --- a/IPython/core/pylabtools.py +++ b/IPython/core/pylabtools.py @@ -5,30 +5,32 @@ # Distributed under the terms of the Modified BSD License. from io import BytesIO +import warnings from IPython.core.display import _pngxy from IPython.utils.decorators import flag_calls # If user specifies a GUI, that dictates the backend, otherwise we read the # user's mpl default from the mpl rc structure -backends = {'tk': 'TkAgg', - 'gtk': 'GTKAgg', - 'gtk3': 'GTK3Agg', - 'wx': 'WXAgg', - 'qt4': 'Qt4Agg', - 'qt5': 'Qt5Agg', - 'qt': 'Qt5Agg', - 'osx': 'MacOSX', - 'nbagg': 'nbAgg', - 'notebook': 'nbAgg', - 'agg': 'agg', - 'svg': 'svg', - 'pdf': 'pdf', - 'ps': 'ps', - 'inline': 'module://ipykernel.pylab.backend_inline', - 'ipympl': 'module://ipympl.backend_nbagg', - 'widget': 'module://ipympl.backend_nbagg', - } +backends = { + "tk": "TkAgg", + "gtk": "GTKAgg", + "gtk3": "GTK3Agg", + "wx": "WXAgg", + "qt4": "Qt4Agg", + "qt5": "Qt5Agg", + "qt": "Qt5Agg", + "osx": "MacOSX", + "nbagg": "nbAgg", + "notebook": "nbAgg", + "agg": "agg", + "svg": "svg", + "pdf": "pdf", + "ps": "ps", + "inline": "module://matplotlib_inline.backend_inline", + "ipympl": "module://ipympl.backend_nbagg", + "widget": "module://ipympl.backend_nbagg", +} # We also need a reverse backends2guis mapping that will properly choose which # GUI support to activate based on the desired matplotlib backend. For the @@ -44,12 +46,12 @@ backend2gui['GTK3Cairo'] = 'gtk3' backend2gui['WX'] = 'wx' backend2gui['CocoaAgg'] = 'osx' # And some backends that don't need GUI integration -del backend2gui['nbAgg'] -del backend2gui['agg'] -del backend2gui['svg'] -del backend2gui['pdf'] -del backend2gui['ps'] -del backend2gui['module://ipykernel.pylab.backend_inline'] +del backend2gui["nbAgg"] +del backend2gui["agg"] +del backend2gui["svg"] +del backend2gui["pdf"] +del backend2gui["ps"] +del backend2gui["module://matplotlib_inline.backend_inline"] #----------------------------------------------------------------------------- # Matplotlib utilities @@ -96,10 +98,10 @@ def figsize(sizex, sizey): def print_figure(fig, fmt='png', bbox_inches='tight', **kwargs): """Print a figure to an image, and return the resulting file data - + Returned data will be bytes unless ``fmt='svg'``, in which case it will be unicode. - + Any keyword args are passed to fig.canvas.print_figure, such as ``quality`` or ``bbox_inches``. """ @@ -112,7 +114,7 @@ def print_figure(fig, fmt='png', bbox_inches='tight', **kwargs): if fmt == 'retina': dpi = dpi * 2 fmt = 'png' - + # build keyword args kw = { "format":fmt, @@ -162,7 +164,7 @@ def mpl_runner(safe_execfile): A function suitable for use as the ``runner`` argument of the %run magic function. """ - + def mpl_execfile(fname,*where,**kw): """matplotlib-aware wrapper around safe_execfile. @@ -243,7 +245,7 @@ def select_figure_formats(shell, formats, **kwargs): bs = "%s" % ','.join([repr(f) for f in bad]) gs = "%s" % ','.join([repr(f) for f in supported]) raise ValueError("supported formats are: %s not %s" % (gs, bs)) - + if 'png' in formats: png_formatter.for_type(Figure, lambda fig: print_figure(fig, 'png', **kwargs)) if 'retina' in formats or 'png2x' in formats: @@ -274,7 +276,7 @@ def find_gui_and_backend(gui=None, gui_select=None): Returns ------- A tuple of (gui, backend) where backend is one of ('TkAgg','GTKAgg', - 'WXAgg','Qt4Agg','module://ipykernel.pylab.backend_inline','agg'). + 'WXAgg','Qt4Agg','module://matplotlib_inline.backend_inline','agg'). """ import matplotlib @@ -308,7 +310,7 @@ def activate_matplotlib(backend): import matplotlib matplotlib.interactive(True) - + # Matplotlib had a bug where even switch_backend could not force # the rcParam to update. This needs to be set *before* the module # magic of switch_backend(). @@ -329,11 +331,11 @@ def activate_matplotlib(backend): def import_pylab(user_ns, import_all=True): """Populate the namespace with pylab-related values. - + Imports matplotlib, pylab, numpy, and everything from pylab and numpy. - + Also imports a few names from IPython (figsize, display, getfigs) - + """ # Import numpy as np/pyplot as plt are conventions we're trying to @@ -346,12 +348,12 @@ def import_pylab(user_ns, import_all=True): "plt = pyplot\n" ) exec(s, user_ns) - + if import_all: s = ("from matplotlib.pylab import *\n" "from numpy import *\n") exec(s, user_ns) - + # IPython symbols to add user_ns['figsize'] = figsize from IPython.display import display @@ -361,7 +363,10 @@ def import_pylab(user_ns, import_all=True): def configure_inline_support(shell, backend): - """Configure an IPython shell object for matplotlib use. + """ + DEPRECATED + + Configure an IPython shell object for matplotlib use. Parameters ---------- @@ -369,51 +374,13 @@ def configure_inline_support(shell, backend): 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. + warnings.warn( + "`configure_inline_support` is deprecated, directly use " + "`matplotlib_inline.backend_inline.configure_inline_support()`", + DeprecationWarning, + stacklevel=2, + ) - # Note: if we can't load the inline backend, then there's no point - # continuing (such as in terminal-only shells in environments without - # zeromq available). - try: - from ipykernel.pylab.backend_inline import InlineBackend - except ImportError: - return - import matplotlib + from matplotlib_inline.backend_inline import configure_inline_support_orig - cfg = InlineBackend.instance(parent=shell) - cfg.shell = shell - if cfg not in shell.configurables: - shell.configurables.append(cfg) - - if backend == backends['inline']: - from ipykernel.pylab.backend_inline import flush_figures - 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: - from ipykernel.pylab.backend_inline import flush_figures - 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 + configure_inline_support_orig(shell, backend) diff --git a/IPython/core/tests/test_display.py b/IPython/core/tests/test_display.py index c5a31d5..f21dfab 100644 --- a/IPython/core/tests/test_display.py +++ b/IPython/core/tests/test_display.py @@ -135,7 +135,7 @@ def test_image_filename_defaults(): nt.assert_is_none(img._repr_jpeg_()) def _get_inline_config(): - from ipykernel.pylab.config import InlineBackend + from matplotlib_inline.config import InlineBackend return InlineBackend.instance() diff --git a/IPython/core/tests/test_pylabtools.py b/IPython/core/tests/test_pylabtools.py index 75b103f..ba59254 100644 --- a/IPython/core/tests/test_pylabtools.py +++ b/IPython/core/tests/test_pylabtools.py @@ -15,6 +15,7 @@ from nose import SkipTest import nose.tools as nt from matplotlib import pyplot as plt +import matplotlib_inline import numpy as np from IPython.core.getipython import get_ipython @@ -167,13 +168,15 @@ class TestPylabSwitch(object): pt.activate_matplotlib = act_mpl self._save_ip = pt.import_pylab pt.import_pylab = lambda *a,**kw:None - self._save_cis = pt.configure_inline_support - pt.configure_inline_support = lambda *a,**kw:None + self._save_cis = matplotlib_inline.backend_inline.configure_inline_support + matplotlib_inline.backend_inline.configure_inline_support = ( + lambda *a, **kw: None + ) def teardown(self): pt.activate_matplotlib = self._save_am pt.import_pylab = self._save_ip - pt.configure_inline_support = self._save_cis + matplotlib_inline.backend_inline.configure_inline_support = self._save_cis import matplotlib matplotlib.rcParams = self._saved_rcParams matplotlib.rcParamsOrig = self._saved_rcParamsOrig diff --git a/setup.py b/setup.py index 4c769a1..f7be18e 100755 --- a/setup.py +++ b/setup.py @@ -191,15 +191,16 @@ extras_require = dict( ) install_requires = [ - 'setuptools>=18.5', - 'jedi>=0.16', - 'decorator', - 'pickleshare', - 'traitlets>=4.2', - 'prompt_toolkit>=2.0.0,<3.1.0,!=3.0.0,!=3.0.1', - 'pygments', - 'backcall', - 'stack_data', + "setuptools>=18.5", + "jedi>=0.16", + "decorator", + "pickleshare", + "traitlets>=4.2", + "prompt_toolkit>=2.0.0,<3.1.0,!=3.0.0,!=3.0.1", + "pygments", + "backcall", + "stack_data", + "matplotlib-inline", ] # Platform-specific dependencies: