Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 95fda41

Browse files
committed
Move draw_if_interactive logic to new_figure_manager_given_figure.
Currently, Matplotlib only ever calls draw_if_interactive at the end of `plt.figure()` (and upon figure unpickling), i.e. this is a mechanism to further customize handling of newly generated figures. (Prior to Matplotlib 1.5, draw_if_interactive was also called at the end of all pyplot functions to trigger a figure redraw, but this is now handled by the stale attribute.) In order to simplify the backend API ("what is the API that a backend module must/can provide", I am planning to deprecate (on Matplotlib's side) the ability for backends to provide a draw_if_interactive function (forcing them to always do `if interactive(): draw_idle()`). Instead, any relevant new-figure-customization logic can instead go into `new_figure_manager_given_figure`. This PR implements this change for matplotlib-inline, and should be fully back-compatible all the way back to Matplotlib 1.5. I would like to make these changes first on the side of the clients (i.e., the third-party backends), to catch any possible problems with the intended change on Matplotlib's side.
1 parent 170a075 commit 95fda41

File tree

1 file changed

+44
-50
lines changed

1 file changed

+44
-50
lines changed

matplotlib_inline/backend_inline.py

Lines changed: 44 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,11 @@
44
# Distributed under the terms of the BSD 3-Clause License.
55

66
import matplotlib
7-
from matplotlib.backends.backend_agg import ( # noqa
8-
new_figure_manager,
9-
FigureCanvasAgg,
10-
new_figure_manager_given_figure,
11-
)
127
from matplotlib import colors
8+
from matplotlib.backends import backend_agg
9+
from matplotlib.backends.backend_agg import FigureCanvasAgg
1310
from matplotlib._pylab_helpers import Gcf
11+
from matplotlib.figure import Figure
1412

1513
from IPython.core.interactiveshell import InteractiveShell
1614
from IPython.core.getipython import get_ipython
@@ -20,6 +18,47 @@
2018
from .config import InlineBackend
2119

2220

21+
def new_figure_manager(num, *args, FigureClass=Figure, **kwargs):
22+
return new_figure_manager_given_figure(num, FigureClass(*args, **kwargs))
23+
24+
25+
def new_figure_manager_given_figure(num, figure):
26+
manager = backend_agg.new_figure_manager_given_figure(num, figure)
27+
28+
# Hack: matplotlib FigureManager objects in interacive backends (at least
29+
# in some of them) monkeypatch the figure object and add a .show() method
30+
# to it. This applies the same monkeypatch in order to support user code
31+
# that might expect `.show()` to be part of the official API of figure
32+
# objects. For further reference:
33+
# https://github.com/ipython/ipython/issues/1612
34+
# https://github.com/matplotlib/matplotlib/issues/835
35+
36+
if not hasattr(figure, 'show'):
37+
# Queue up `figure` for display
38+
figure.show = lambda *a: display(
39+
figure, metadata=_fetch_figure_metadata(figure))
40+
41+
# If matplotlib was manually set to non-interactive mode, this function
42+
# should be a no-op (otherwise we'll generate duplicate plots, since a user
43+
# who set ioff() manually expects to make separate draw/show calls).
44+
if not matplotlib.is_interactive():
45+
return
46+
47+
# ensure current figure will be drawn, and each subsequent call
48+
# of draw_if_interactive() moves the active figure to ensure it is
49+
# drawn last
50+
try:
51+
show._to_draw.remove(figure)
52+
except ValueError:
53+
# ensure it only appears in the draw list once
54+
pass
55+
# Queue up the figure for drawing in next show() call
56+
show._to_draw.append(figure)
57+
show._draw_called = True
58+
59+
return manager
60+
61+
2362
def show(close=None, block=None):
2463
"""Show all figures as SVG/PNG payloads sent to the IPython clients.
2564
@@ -56,51 +95,6 @@ def show(close=None, block=None):
5695
show._to_draw = []
5796

5897

59-
def draw_if_interactive():
60-
"""
61-
Is called after every pylab drawing command
62-
"""
63-
# signal that the current active figure should be sent at the end of
64-
# execution. Also sets the _draw_called flag, signaling that there will be
65-
# something to send. At the end of the code execution, a separate call to
66-
# flush_figures() will act upon these values
67-
manager = Gcf.get_active()
68-
if manager is None:
69-
return
70-
fig = manager.canvas.figure
71-
72-
# Hack: matplotlib FigureManager objects in interacive backends (at least
73-
# in some of them) monkeypatch the figure object and add a .show() method
74-
# to it. This applies the same monkeypatch in order to support user code
75-
# that might expect `.show()` to be part of the official API of figure
76-
# objects.
77-
# For further reference:
78-
# https://github.com/ipython/ipython/issues/1612
79-
# https://github.com/matplotlib/matplotlib/issues/835
80-
81-
if not hasattr(fig, 'show'):
82-
# Queue up `fig` for display
83-
fig.show = lambda *a: display(fig, metadata=_fetch_figure_metadata(fig))
84-
85-
# If matplotlib was manually set to non-interactive mode, this function
86-
# should be a no-op (otherwise we'll generate duplicate plots, since a user
87-
# who set ioff() manually expects to make separate draw/show calls).
88-
if not matplotlib.is_interactive():
89-
return
90-
91-
# ensure current figure will be drawn, and each subsequent call
92-
# of draw_if_interactive() moves the active figure to ensure it is
93-
# drawn last
94-
try:
95-
show._to_draw.remove(fig)
96-
except ValueError:
97-
# ensure it only appears in the draw list once
98-
pass
99-
# Queue up the figure for drawing in next show() call
100-
show._to_draw.append(fig)
101-
show._draw_called = True
102-
103-
10498
def flush_figures():
10599
"""Send all figures that changed
106100

0 commit comments

Comments
 (0)