8000 inspect running framework to decide if destroy should be delayed · matplotlib/matplotlib@b59a89e · GitHub
[go: up one dir, main page]

Skip to content

Commit b59a89e

Browse files
inspect running framework to decide if destroy should be delayed
1 parent 2056ce1 commit b59a89e

File tree

3 files changed

+18
-15
lines changed

3 files changed

+18
-15
lines changed

lib/matplotlib/backends/_backend_tk.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -474,18 +474,22 @@ def destroy(self, *args):
474474
self.canvas._tkcanvas.after_cancel(self.canvas._event_loop_id)
475475

476476
# NOTE: events need to be flushed before issuing destroy (GH #9956),
477-
# however, self.window.update() can break user code. This is the
478-
# safest way to achieve a complete draining of the event queue,
479-
# but it may require users to update() on their own to execute the
480-
# completion in obscure corner cases.
477+
# however, self.window.update() can break user code. An async callback
478+
# is the safest way to achieve a complete draining of the event queue,
479+
# but it leaks if no tk event loop is running. Therefore we explicitly
480+
# check for an event loop and choose our best guess.
481481
def delayed_destroy():
482482
self.window.destroy()
483483

484484
if self._owns_mainloop and not Gcf.get_num_fig_managers():
485485
self.window.quit()
486486

487-
# "after idle after 0" avoids Tcl error/race (GH #19940)
488-
self.window.after_idle(self.window.after, 0, delayed_destroy)
487+
if cbook._get_running_interactive_framework() == "tk":
488+
# "after idle after 0" avoids Tcl error/race (GH #19940)
489+
self.window.after_idle(self.window.after, 0, delayed_destroy)
490+
else:
491+
self.window.update()
492+
delayed_destroy()
489493

490494
def get_window_title(self):
491495
return self.window.wm_title()

lib/matplotlib/tests/test_backend_tk.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,9 @@ def test_func():
5050
)
5151
except subprocess.TimeoutExpired:
5252
pytest.fail("Subprocess timed out")
53-
except subprocess.CalledProcessError:
54-
pytest.fail("Subprocess failed to test intended behavior")
53+
except subprocess.CalledProcessError as e:
54+
pytest.fail("Subprocess failed to test intended behavior\n"
55+
+ str(e.stderr))
5556
else:
5657
# macOS may actually emit irrelevant errors about Accelerated
5758
# OpenGL vs. software OpenGL, so suppress them.
@@ -146,6 +147,7 @@ def target():
146147
thread.join()
147148

148149

150+
@pytest.mark.backend('TkAgg', skip_on_importerror=True)
149151
@pytest.mark.flaky(reruns=3)
150152
@_isolated_tk_test(success_count=0)
151153
def test_never_update():
@@ -159,14 +161,12 @@ def test_never_update():
159161

160162
plt.draw() # Test FigureCanvasTkAgg.
161163
fig.canvas.toolbar.configure_subplots() # Test NavigationToolbar2Tk.
164+
# Test FigureCanvasTk filter_destroy callback
165+
fig.canvas.get_tk_widget().after(100, plt.close, fig)
162166

163167
# Check for update() or update_idletasks() in the event queue, functionally
164168
# equivalent to tkinter.Misc.update.
165-
# Must pause >= 1 ms to process tcl idle events plus extra time to avoid
166-
# flaky tests on slow systems.
167-
plt.pause(0.1)
168-
169-
plt.close(fig) # Test FigureCanvasTk filter_destroy callback
169+
plt.show(block=True)
170170

171171
# Note that exceptions would be printed to stderr; _isolated_tk_test
172172
# checks them.

lib/matplotlib/tests/test_backends_interactive.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -195,8 +195,7 @@ def _test_thread_impl():
195195
future = ThreadPoolExecutor().submit(fig.canvas.draw)
196196
plt.pause(0.5) # flush_events fails here on at least Tkagg (bpo-41176)
197197
future.result() # Joins the thread; rethrows any exception.
198-
plt.close()
199-
fig.canvas.flush_events() # pause doesn't process events after close
198+
plt.close() # backend is responsible for flushing any events here
200199

201200

202201
_thread_safe_backends = _get_testable_interactive_backends()

0 commit comments

Comments
 (0)
0