@@ -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