Skip to content

Commit b130b75

Browse files
committed
TST: Test number of draw events from a blitted animation
This adds a test that only one draw_event is called when using blitting with animations. There will be more than one draw_event if blitting is not implemented properly and instead calls a full redraw of the canvas.
1 parent 90b354b commit b130b75

File tree

1 file changed

+54
-0
lines changed

1 file changed

+54
-0
lines changed

lib/matplotlib/tests/test_backends_interactive.py

+54
Original file line numberDiff line numberDiff line change
@@ -319,3 +319,57 @@ def test_lazy_linux_headless():
319319
if proc.returncode:
320320
pytest.fail("The subprocess returned with non-zero exit status "
321321
f"{proc.returncode}.")
322+
323+
324+
def _test_number_of_draws_script():
325+
from matplotlib import animation
326+
import matplotlib.pyplot as plt
327+
328+
# If blitting is respected, this should result in
329+
# only one "draw_event" being emitted
330+
fig, ax = plt.subplots()
331+
332+
def animate(i):
333+
# Create a new marker every time, instead of updating data
334+
# this "misuse" of animate can trip up blitting, but it should
335+
# not emit a new draw_event
336+
return ax.plot(0, 0)
337+
338+
# Show the empty figure initially because some backends emit a
339+
# draw event on canvas initialization, which we aren't interested
340+
# in counting
341+
plt.show(block=False)
342+
plt.pause(0.1)
343+
344+
# Connect to draw_event to count the number of events received
345+
fig.canvas.mpl_connect('draw_event', print)
346+
347+
ani = animation.FuncAnimation(
348+
fig, animate, frames=10, blit=True, repeat=False)
349+
350+
plt.show(block=False)
351+
# Give the animation some time to draw before closing
352+
# calling plt.close() from within the animation causes the
353+
# animation timers to be called on a Nonetype object, potentially
354+
# causing segfaults or anomalous failures
355+
plt.pause(0.5)
356+
357+
358+
@pytest.mark.parametrize("env", _get_testable_interactive_backends())
359+
def test_number_of_draws(env):
360+
if env["MPLBACKEND"].startswith("gtk"):
361+
# FIXME
362+
pytest.skip("GTK animation calls draw too many times")
363+
364+
proc = subprocess.run(
365+
[sys.executable, "-c",
366+
inspect.getsource(_test_number_of_draws_script)
367+
+ "\n_test_number_of_draws_script()"],
368+
env={**os.environ, "SOURCE_DATE_EPOCH": "0", **env},
369+
timeout=_test_timeout,
370+
stdout=subprocess.PIPE, universal_newlines=True)
371+
if proc.returncode:
372+
pytest.fail("The subprocess returned with non-zero exit status "
373+
f"{proc.returncode}.")
374+
# Make sure we only got one draw event from the animation
375+
assert proc.stdout.count("DrawEvent") == 1

0 commit comments

Comments
 (0)