11import os
22import subprocess
33import sys
4- import tkinter
54
65import numpy as np
76import pytest
87
98from matplotlib import pyplot as plt
9+ _test_timeout = 10 # Empirically, 1s is not enough on Travis.
1010
1111
1212@pytest .mark .backend ('TkAgg' , skip_on_importerror = True )
@@ -36,25 +36,42 @@ def evil_blit(photoimage, aggimage, offsets, bboxptr):
3636
3737@pytest .mark .backend ('TkAgg' , skip_on_importerror = True )
3838def test_figuremanager_preserves_host_mainloop ():
39- success = False
40-
41- def do_plot ():
42- plt .figure ()
43- plt .plot ([1 , 2 ], [3 , 5 ])
44- plt .close ()
45- root .after (0 , legitimate_quit )
39+ script = """
40+ import tkinter
41+ import matplotlib.pyplot as plt
42+ success = False
4643
47- def legitimate_quit ():
48- root .quit ()
49- nonlocal success
50- success = True
44+ def do_plot():
45+ plt.figure()
46+ plt.plot([1, 2], [3, 5])
47+ plt.close()
48+ root.after(0, legitimate_quit)
5149
52- root = tkinter .Tk ()
53- root .after (0 , do_plot )
54- root .mainloop ()
50+ def legitimate_quit():
51+ root.quit()
52+ global success
53+ success = True
5554
56- assert success
55+ root = tkinter.Tk()
56+ root.after(0, do_plot)
57+ root.mainloop()
5758
59+ if success:
60+ print("success")
61+ """
62+ try :
63+ proc = subprocess .run (
64+ [sys .executable , "-c" , script ,],
65+ env = {** os .environ , "SOURCE_DATE_EPOCH" : "0" },
66+ timeout = _test_timeout ,
67+ stdout = subprocess .PIPE ,
68+ check = True ,
69+ universal_newlines = True ,
70+ )
71+ except subprocess .CalledProcessError :
72+ pytest .fail ("Subprocess failed to test intended behavior" )
73+ else :
74+ assert proc .stdout .count ("success" ) == 1
5875
5976@pytest .mark .backend ('TkAgg' , skip_on_importerror = True )
6077@pytest .mark .flaky (reruns = 3 )
@@ -90,7 +107,7 @@ def target():
90107 env = {** os .environ ,
91108 "MPLBACKEND" : "TkAgg" ,
92109 "SOURCE_DATE_EPOCH" : "0" },
93- timeout = 10 ,
110+ timeout = _test_timeout ,
94111 stdout = subprocess .PIPE ,
95112 universal_newlines = True ,
96113 check = True
@@ -102,6 +119,52 @@ def target():
102119 assert proc .stdout .count ("success" ) == 1
103120
104121
122+ @pytest .mark .backend ('TkAgg' , skip_on_importerror = True )
123+ @pytest .mark .flaky (reruns = 3 )
124+ def test_never_update ():
125+ script = """
126+ import tkinter
127+ del tkinter.Misc.update
128+ del tkinter.Misc.update_idletasks
129+
130+ import matplotlib.pyplot as plt
131+ fig = plt.figure()
132+ plt.show(block=False)
133+
134+ # regression test on FigureCanvasTkAgg
135+ plt.draw()
136+ # regression test on NavigationToolbar2Tk
137+ fig.canvas.toolbar.configure_subplots()
138+
139+ # check for update() or update_idletasks() in the event queue
140+ # functionally equivalent to tkinter.Misc.update
141+ # must pause >= 1 ms to process tcl idle events plus
142+ # extra time to avoid flaky tests on slow systems
143+ plt.pause(0.1)
144+
145+ # regression test on FigureCanvasTk filter_destroy callback
146+ plt.close(fig)
147+ """
148+ try :
149+ proc = subprocess .run (
150+ [sys .executable , "-c" , script ,],
151+ env = {** os .environ , "SOURCE_DATE_EPOCH" : "0" },
152+ timeout = _test_timeout ,
153+ capture_output = True ,
154+ check = True ,
155+ universal_newlines = True ,
156+ )
157+ except subprocess .CalledProcessError :
158+ pytest .fail ("Subprocess failed to test intended behavior" )
159+ else :
160+ # test framework doesn't see tkinter callback exceptions normally
161+ # see tkinter.Misc.report_callback_exception
162+ assert "Exception in Tkinter callback" not in proc .stderr
163+ finally :
164+ # make sure we can see other issues
165+ print (proc .stderr , file = sys .stderr )
166+
167+
105168@pytest .mark .backend ('TkAgg' , skip_on_importerror = True )
106169def test_missing_back_button ():
107170 from matplotlib .backends .backend_tkagg import NavigationToolbar2Tk
0 commit comments