Skip to content

Commit eb18cb2

Browse files
authored
Merge pull request #16078 from anntzer/animstart
Refactor a bit animation start/save interaction.
2 parents f4c25b2 + b384e57 commit eb18cb2

File tree

2 files changed

+12
-23
lines changed

2 files changed

+12
-23
lines changed

lib/matplotlib/animation.py

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -939,9 +939,11 @@ def _start(self, *args):
939939
Starts interactive animation. Adds the draw frame command to the GUI
940940
handler, calls show to start the event loop.
941941
"""
942+
# Do not start the event source if saving() it.
943+
if self._fig.canvas.is_saving():
944+
return
942945
# First disconnect our draw event handler
943946
self._fig.canvas.mpl_disconnect(self._first_draw_id)
944-
self._first_draw_id = None # So we can check on save
945947

946948
# Now do any initial draw
947949
self._init_draw()
@@ -1057,14 +1059,6 @@ def func(current_frame: int, total_frames: int) -> Any
10571059
if savefig_kwargs is None:
10581060
savefig_kwargs = {}
10591061

1060-
# Need to disconnect the first draw callback, since we'll be doing
1061-
# draws. Otherwise, we'll end up starting the animation.
1062-
if self._first_draw_id is not None:
1063-
self._fig.canvas.mpl_disconnect(self._first_draw_id)
1064-
reconnect_first_draw = True
1065-
else:
1066-
reconnect_first_draw = False
1067-
10681062
if fps is None and hasattr(self, '_interval'):
10691063
# Convert interval in ms to frames per second
10701064
fps = 1000. / self._interval
@@ -1123,8 +1117,11 @@ def func(current_frame: int, total_frames: int) -> Any
11231117
_log.info("Disabling savefig.bbox = 'tight', as it may cause "
11241118
"frame size to vary, which is inappropriate for "
11251119
"animation.")
1120+
# canvas._is_saving = True makes the draw_event animation-starting
1121+
# callback a no-op.
11261122
with mpl.rc_context({'savefig.bbox': None}), \
1127-
writer.saving(self._fig, filename, dpi):
1123+
writer.saving(self._fig, filename, dpi), \
1124+
cbook._setattr_cm(self._fig.canvas, _is_saving=True):
11281125
for anim in all_anim:
11291126
anim._init_draw() # Clear the initial frame
11301127
frame_number = 0
@@ -1145,11 +1142,6 @@ def func(current_frame: int, total_frames: int) -> Any
11451142
frame_number += 1
11461143
writer.grab_frame(**savefig_kwargs)
11471144

1148-
# Reconnect signal for first draw if necessary
1149-
if reconnect_first_draw:
1150-
self._first_draw_id = self._fig.canvas.mpl_connect('draw_event',
1151-
self._start)
1152-
11531145
def _step(self, *args):
11541146
"""
11551147
Handler for getting events. By default, gets the next frame in the

lib/matplotlib/tests/test_animation.py

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -237,13 +237,8 @@ def test_failing_ffmpeg(tmpdir, monkeypatch):
237237
make_animation().save("test.mpeg")
238238

239239

240-
@pytest.mark.parametrize("cache_frame_data, weakref_assertion_fn", [
241-
pytest.param(
242-
False, lambda ref: ref is None, id='cache_frame_data_is_disabled'),
243-
pytest.param(
244-
True, lambda ref: ref is not None, id='cache_frame_data_is_enabled'),
245-
])
246-
def test_funcanimation_holding_frames(cache_frame_data, weakref_assertion_fn):
240+
@pytest.mark.parametrize("cache_frame_data", [False, True])
241+
def test_funcanimation_cache_frame_data(cache_frame_data):
247242
fig, ax = plt.subplots()
248243
line, = ax.plot([], [])
249244

@@ -282,4 +277,6 @@ def frames_generator():
282277
anim.save('unused.null', writer=writer)
283278
assert len(frames_generated) == 5
284279
for f in frames_generated:
285-
assert weakref_assertion_fn(f())
280+
# If cache_frame_data is True, then the weakref should be alive;
281+
# if cache_frame_data is False, then the weakref should be dead (None).
282+
assert (f() is None) != cache_frame_data

0 commit comments

Comments
 (0)