Skip to content

Commit

Permalink
Use matplotlib-inline instead of ipykernel.pylab
Browse files Browse the repository at this point in the history
  • Loading branch information
martinRenou committed Apr 15, 2021
1 parent eb9b2bd commit a7d4c74
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 113 deletions.
49 changes: 33 additions & 16 deletions IPython/core/display.py
Expand Up @@ -371,7 +371,7 @@ def reload(self):
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
Expand Down Expand Up @@ -1155,7 +1155,10 @@ def reload(self):

@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%::
Expand All @@ -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
Expand All @@ -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)
3 changes: 2 additions & 1 deletion IPython/core/interactiveshell.py
Expand Up @@ -3514,6 +3514,7 @@ def enable_matplotlib(self, gui=None):
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':
Expand All @@ -3527,7 +3528,7 @@ def enable_matplotlib(self, gui=None):
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
Expand Down
133 changes: 50 additions & 83 deletions IPython/core/pylabtools.py
Expand Up @@ -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
Expand All @@ -44,12 +46,12 @@
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
Expand Down Expand Up @@ -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``.
"""
Expand All @@ -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,
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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().
Expand All @@ -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
Expand All @@ -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
Expand All @@ -361,59 +363,24 @@ 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
----------
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.
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

This comment has been minimized.

Copy link
@MrBago

MrBago May 3, 2021

@martinRenou did you mean to include a rename in the import here? This import doesn't seem to reference anything that exists.

#12941

This comment has been minimized.

Copy link
@martinRenou

martinRenou May 4, 2021

Author Contributor

No, this was definitely a mistake. #12940 should fix it.


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)
2 changes: 1 addition & 1 deletion IPython/core/tests/test_display.py
Expand Up @@ -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()


Expand Down
9 changes: 6 additions & 3 deletions IPython/core/tests/test_pylabtools.py
Expand Up @@ -15,6 +15,7 @@
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
Expand Down Expand Up @@ -167,13 +168,15 @@ def act_mpl(backend):
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
Expand Down
19 changes: 10 additions & 9 deletions setup.py
Expand Up @@ -191,15 +191,16 @@
)

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:
Expand Down

0 comments on commit a7d4c74

Please sign in to comment.