From f7043b613bdeed6ec8b216ddd4d0ac58d9df35f8 Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Mon, 21 Nov 2022 00:23:11 +0100 Subject: [PATCH] Fix testing of whether backends use the new pyplot_show API. See comment in pyplot.py explaining the change, and the associated tests. I chose to directly break backcompat on backend_template (removing the global show) as that backend essentially serves as documentation of how to define a backend, so it seems better to directly showcase the encouraged approach. --- doc/api/next_api_changes/removals/XXXXX-AL.rst | 4 ++++ lib/matplotlib/backends/backend_template.py | 16 +++------------- lib/matplotlib/pyplot.py | 10 ++++++++-- lib/matplotlib/tests/test_backend_template.py | 16 +++++++++++++--- 4 files changed, 28 insertions(+), 18 deletions(-) create mode 100644 doc/api/next_api_changes/removals/XXXXX-AL.rst diff --git a/doc/api/next_api_changes/removals/XXXXX-AL.rst b/doc/api/next_api_changes/removals/XXXXX-AL.rst new file mode 100644 index 000000000000..490519c2c650 --- /dev/null +++ b/doc/api/next_api_changes/removals/XXXXX-AL.rst @@ -0,0 +1,4 @@ +``backend_template.show`` +~~~~~~~~~~~~~~~~~~~~~~~~~ +... has been removed, in order to better demonstrate the new backend definition +API. diff --git a/lib/matplotlib/backends/backend_template.py b/lib/matplotlib/backends/backend_template.py index 67aea9d811f0..e4b3d79bd49b 100644 --- a/lib/matplotlib/backends/backend_template.py +++ b/lib/matplotlib/backends/backend_template.py @@ -136,23 +136,13 @@ class GraphicsContextTemplate(GraphicsContextBase): ######################################################################## -def show(*, block=None): - """ - For image backends - is not required. - For GUI backends - show() is usually the last line of a pyplot script and - tells the backend that it is time to draw. In interactive mode, this - should do nothing. - """ - for manager in Gcf.get_all_fig_managers(): - # do something to display the GUI - pass - - class FigureManagerTemplate(FigureManagerBase): """ Helper class for pyplot mode, wraps everything up into a neat bundle. - For non-interactive backends, the base class is sufficient. + For non-interactive backends, the base class is sufficient. For + interactive backends, see the documentation of the `.FigureManagerBase` + class for the list of methods that can/should be overridden. """ diff --git a/lib/matplotlib/pyplot.py b/lib/matplotlib/pyplot.py index 34d46eeac918..58571c17b124 100644 --- a/lib/matplotlib/pyplot.py +++ b/lib/matplotlib/pyplot.py @@ -325,8 +325,14 @@ def draw_if_interactive(): # show is already present, as the latter may be here for backcompat. manager_class = getattr(getattr(backend_mod, "FigureCanvas", None), "manager_class", None) - if (manager_class.pyplot_show != FigureManagerBase.pyplot_show - or show is None): + # We can't compare directly manager_class.pyplot_show and FMB.pyplot_show + # because pyplot_show is a classmethod so the above constructs are bound + # classmethods, & thus always different (being bound to different classes). + manager_pyplot_show = vars(manager_class).get("pyplot_show") + base_pyplot_show = vars(FigureManagerBase).get("pyplot_show") + if (show is None + or (manager_pyplot_show is not None + and manager_pyplot_show != base_pyplot_show)): backend_mod.show = manager_class.pyplot_show _log.debug("Loaded backend %s version %s.", diff --git a/lib/matplotlib/tests/test_backend_template.py b/lib/matplotlib/tests/test_backend_template.py index 1bc666ce1814..d7e2a5cd1266 100644 --- a/lib/matplotlib/tests/test_backend_template.py +++ b/lib/matplotlib/tests/test_backend_template.py @@ -32,9 +32,19 @@ def test_load_old_api(monkeypatch): def test_show(monkeypatch): mpl_test_backend = SimpleNamespace(**vars(backend_template)) - mock_show = backend_template.FigureManagerTemplate.pyplot_show = \ - MagicMock() - del mpl_test_backend.show + mock_show = MagicMock() + monkeypatch.setattr( + mpl_test_backend.FigureManagerTemplate, "pyplot_show", mock_show) + monkeypatch.setitem(sys.modules, "mpl_test_backend", mpl_test_backend) + mpl.use("module://mpl_test_backend") + plt.show() + mock_show.assert_called_with() + + +def test_show_old_global_api(monkeypatch): + mpl_test_backend = SimpleNamespace(**vars(backend_template)) + mock_show = MagicMock() + monkeypatch.setattr(mpl_test_backend, "show", mock_show, raising=False) monkeypatch.setitem(sys.modules, "mpl_test_backend", mpl_test_backend) mpl.use("module://mpl_test_backend") plt.show()