@@ -146,8 +146,51 @@ def check_alt_backend(alt_backend):
146
146
# FIXME: This should be enabled everywhere once Qt5 is fixed on macOS to
147
147
# not resize incorrectly.
148
148
assert_equal(result.getvalue(), result_after.getvalue())
149
+ """
150
+ _test_timeout = 10 # Empirically, 1s is not enough on Travis.
151
+
152
+
153
+ @pytest .mark .parametrize ("backend" , _get_testable_interactive_backends ())
154
+ @pytest .mark .parametrize ("toolbar" , ["toolbar2" , "toolmanager" ])
155
+ @pytest .mark .flaky (reruns = 3 )
156
+ def test_interactive_backend (backend , toolbar ):
157
+ if backend == "macosx" :
158
+ if toolbar == "toolmanager" :
159
+ pytest .skip ("toolmanager is not implemented for macosx." )
160
+ if toolbar == "toolbar2" and os .environ .get ('TRAVIS' ):
161
+ # See https://github.com/matplotlib/matplotlib/issues/18213
162
+ pytest .skip ("toolbar2 for macosx is buggy on Travis." )
163
+
164
+ proc = subprocess .run (
165
+ [sys .executable , "-c" , _test_script ,
166
+ json .dumps ({"toolbar" : toolbar })],
167
+ env = {** os .environ , "MPLBACKEND" : backend , "SOURCE_DATE_EPOCH" : "0" },
168
+ timeout = _test_timeout
10000
span>,
169
+ stdout = subprocess .PIPE , universal_newlines = True )
170
+ if proc .returncode :
171
+ pytest .fail ("The subprocess returned with non-zero exit status "
172
+ f"{ proc .returncode } ." )
173
+ assert proc .stdout .count ("CloseEvent" ) == 1
174
+
175
+
176
+ _thread_test_script = """\
177
+ import json
178
+ import sys
179
+ import threading
180
+ from unittest import TestCase
181
+
182
+ from matplotlib import pyplot as plt, rcParams
183
+ rcParams.update({
184
+ "webagg.open_in_browser": False,
185
+ "webagg.port_retries": 1,
186
+ })
187
+ if len(sys.argv) >= 2: # Second argument is json-encoded rcParams.
188
+ rcParams.update(json.loads(sys.argv[1]))
189
+ assert_equal = TestCase().assertEqual
190
+ assert_raises = TestCase().assertRaises
149
191
150
- # Test artists and drawing does not crash from thread (no other guarantees)
192
+ # Test artist creation and drawing does not crash from thread
193
+ # No other guarantees!
151
194
fig, ax = plt.subplots()
152
195
# plt.pause needed vs plt.show(block=False) at least on toolbar2-tkagg
153
196
plt.pause(0.1)
@@ -159,6 +202,7 @@ def thread_artist_work():
159
202
ax.plot([1,3,6])
160
203
except:
161
204
# Propagate error to main thread
205
+ import sys
162
206
global exc_info
163
207
exc_info = sys.exc_info()
164
208
@@ -167,6 +211,7 @@ def thread_draw_work():
167
211
fig.canvas.draw()
168
212
except:
169
213
# Propagate error to main thread
214
+ import sys
170
215
global exc_info
171
216
exc_info = sys.exc_info()
172
217
@@ -181,38 +226,30 @@ def thread_draw_work():
181
226
t = threading.Thread(target=thread_draw_work)
182
227
fig.canvas.mpl_connect("close_event", print)
183
228
t.start()
184
- plt.pause(0.1) # flush_events fails on at least Tkagg (bpo-41176)
229
+ plt.pause(0.1) # flush_events fails here on at least Tkagg (bpo-41176)
185
230
t.join()
186
231
plt.close()
187
232
fig.canvas.flush_events() # pause doesn't process events after close
188
233
189
234
if exc_info: # Raise thread error
190
235
raise exc_info[1].with_traceback(exc_info[2])
191
236
"""
192
- _test_timeout = 10 # Empirically, 1s is not enough on Travis.
193
237
194
238
195
239
@pytest .mark .parametrize ("backend" , _get_testable_interactive_backends ())
196
- @pytest .mark .parametrize ("toolbar" , ["toolbar2" , "toolmanager" ])
197
240
@pytest .mark .flaky (reruns = 3 )
198
- def test_interactive_backend (backend , toolbar ):
199
- if backend == "macosx" :
200
- if toolbar == "toolmanager" :
201
- pytest .skip ("toolmanager is not implemented for macosx." )
202
- if toolbar == "toolbar2" and os .environ .get ('TRAVIS' ):
203
- # See https://github.com/matplotlib/matplotlib/issues/18213
204
- pytest .skip ("toolbar2 for macosx is buggy on Travis." )
205
-
241
+ def test_interactive_thread_safety (backend ):
206
242
proc = subprocess .run (
207
- [sys .executable , "-c" , _test_script ,
208
- json .dumps ({"toolbar" : toolbar })],
243
+ [sys .executable , "-c" , _thread_test_script ],
209
244
env = {** os .environ , "MPLBACKEND" : backend , "SOURCE_DATE_EPOCH" : "0" },
210
245
timeout = _test_timeout ,
211
246
stdout = subprocess .PIPE , universal_newlines = True )
212
247
if proc .returncode :
248
+ if backend == "wx" :
249
+ pytest .xfail ("Ignoring deprecated wx failure. Use wxagg." )
213
250
pytest .fail ("The subprocess returned with non-zero exit status "
214
251
f"{ proc .returncode } ." )
215
- assert proc .stdout .count ("CloseEvent" ) == 2
252
+ assert proc .stdout .count ("CloseEvent" ) == 1
216
253
217
254
218
255
@pytest .mark .skipif ('TF_BUILD' in os .environ ,
0 commit comments