From 8d7ccb08bf6eaaa11ddc6285bf042cbbc399c68d Mon Sep 17 00:00:00 2001 From: Felix Goudreault Date: Tue, 7 Feb 2023 14:05:19 -0500 Subject: [PATCH 1/4] Fix issue #25164 --- lib/matplotlib/backends/_backend_tk.py | 2 ++ lib/matplotlib/tests/test_backend_tk.py | 36 ++++++++++++++++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/lib/matplotlib/backends/_backend_tk.py b/lib/matplotlib/backends/_backend_tk.py index e29b5a7be320..21e29378c81d 100644 --- a/lib/matplotlib/backends/_backend_tk.py +++ b/lib/matplotlib/backends/_backend_tk.py @@ -747,6 +747,8 @@ def _recolor_icon(image, color): # Use the high-resolution (48x48 px) icon if it exists and is needed with Image.open(path_large if (size > 24 and path_large.exists()) else path_regular) as im: + # assure a RGBA image as foreground color is RGB + im = im.convert("RGBA") image = ImageTk.PhotoImage(im.resize((size, size)), master=self) button._ntimage = image diff --git a/lib/matplotlib/tests/test_backend_tk.py b/lib/matplotlib/tests/test_backend_tk.py index eefaefbb023f..5271e0381654 100644 --- a/lib/matplotlib/tests/test_backend_tk.py +++ b/lib/matplotlib/tests/test_backend_tk.py @@ -4,11 +4,19 @@ import platform import subprocess import sys +import tempfile +import warnings + +from PIL import Image import pytest -from matplotlib.testing import subprocess_run_helper +import matplotlib from matplotlib import _c_internal_utils +from matplotlib.backend_tools import ToolToggleBase +from matplotlib.testing import subprocess_run_helper +import matplotlib.pyplot as plt + _test_timeout = 60 # A reasonably safe value for slower architectures. @@ -177,6 +185,32 @@ def test_never_update(): # checks them. +@pytest.mark.backend('TkAgg', skip_on_importerror=True) +@_isolated_tk_test(success_count=0) +def test_toolbar_button_la_mode_icon(): + # test that icon in LA mode can be used for buttons + # see GH#25164 + # tweaking toolbar raises an UserWarning + with warnings.catch_warnings(): + warnings.simplefilter("ignore", UserWarning) + matplotlib.rcParams["toolbar"] = "toolmanager" + + # create an icon in LA mode + with tempfile.TemporaryDirectory() as tempdir: + img = Image.new("LA", (26, 26)) + tmp_img_path = os.path.join(tempdir, "test_la_icon.png") + img.save(tmp_img_path) + + class CustomTool(ToolToggleBase): + image = tmp_img_path + + fig = plt.figure() + toolmanager = fig.canvas.manager.toolmanager + toolbar = fig.canvas.manager.toolbar + toolmanager.add_tool("test", CustomTool) + toolbar.add_tool("test", "group") + + @_isolated_tk_test(success_count=2) def test_missing_back_button(): import matplotlib.pyplot as plt From cb89b0121e295e51baeb9a5d741025aed0e1d163 Mon Sep 17 00:00:00 2001 From: Felix Goudreault Date: Wed, 8 Feb 2023 13:29:56 -0500 Subject: [PATCH 2/4] Generalize test for multiple backends. --- lib/matplotlib/tests/test_backend_tk.py | 33 -------------- lib/matplotlib/tests/test_backend_tools.py | 51 +++++++++++++++++++++- 2 files changed, 50 insertions(+), 34 deletions(-) diff --git a/lib/matplotlib/tests/test_backend_tk.py b/lib/matplotlib/tests/test_backend_tk.py index 5271e0381654..f3257acd5bd3 100644 --- a/lib/matplotlib/tests/test_backend_tk.py +++ b/lib/matplotlib/tests/test_backend_tk.py @@ -4,18 +4,11 @@ import platform import subprocess import sys -import tempfile -import warnings - -from PIL import Image import pytest -import matplotlib from matplotlib import _c_internal_utils -from matplotlib.backend_tools import ToolToggleBase from matplotlib.testing import subprocess_run_helper -import matplotlib.pyplot as plt _test_timeout = 60 # A reasonably safe value for slower architectures. @@ -185,32 +178,6 @@ def test_never_update(): # checks them. -@pytest.mark.backend('TkAgg', skip_on_importerror=True) -@_isolated_tk_test(success_count=0) -def test_toolbar_button_la_mode_icon(): - # test that icon in LA mode can be used for buttons - # see GH#25164 - # tweaking toolbar raises an UserWarning - with warnings.catch_warnings(): - warnings.simplefilter("ignore", UserWarning) - matplotlib.rcParams["toolbar"] = "toolmanager" - - # create an icon in LA mode - with tempfile.TemporaryDirectory() as tempdir: - img = Image.new("LA", (26, 26)) - tmp_img_path = os.path.join(tempdir, "test_la_icon.png") - img.save(tmp_img_path) - - class CustomTool(ToolToggleBase): - image = tmp_img_path - - fig = plt.figure() - toolmanager = fig.canvas.manager.toolmanager - toolbar = fig.canvas.manager.toolbar - toolmanager.add_tool("test", CustomTool) - toolbar.add_tool("test", "group") - - @_isolated_tk_test(success_count=2) def test_missing_back_button(): import matplotlib.pyplot as plt diff --git a/lib/matplotlib/tests/test_backend_tools.py b/lib/matplotlib/tests/test_backend_tools.py index cc05a1a98f78..2d37a9606a00 100644 --- a/lib/matplotlib/tests/test_backend_tools.py +++ b/lib/matplotlib/tests/test_backend_tools.py @@ -1,6 +1,17 @@ +import os +import subprocess +import tempfile +from PIL import Image + import pytest -from matplotlib.backend_tools import ToolHelpBase +import matplotlib +from matplotlib.backend_tools import ToolHelpBase, ToolToggleBase +import matplotlib.pyplot as plt +from matplotlib.testing import subprocess_run_helper +from .test_backends_interactive import ( + _get_testable_interactive_backends, _test_timeout, + ) @pytest.mark.parametrize('rc_shortcut,expected', [ @@ -18,3 +29,41 @@ ]) def test_format_shortcut(rc_shortcut, expected): assert ToolHelpBase.format_shortcut(rc_shortcut) == expected + + +def _test_toolbar_button_la_mode_icon_inside_subprocess(): + matplotlib.rcParams["toolbar"] = "toolmanager" + # create an icon in LA mode + with tempfile.TemporaryDirectory() as tempdir: + img = Image.new("LA", (26, 26)) + tmp_img_path = os.path.join(tempdir, "test_la_icon.png") + img.save(tmp_img_path) + + class CustomTool(ToolToggleBase): + image = tmp_img_path + description = "" # gtk3 backend does not allow None + + fig = plt.figure() + toolmanager = fig.canvas.manager.toolmanager + toolbar = fig.canvas.manager.toolbar + toolmanager.add_tool("test", CustomTool) + toolbar.add_tool("test", "group") + + +@pytest.mark.parametrize( + "env", + _get_testable_interactive_backends(), + ) +def test_toolbar_button_la_mode_icon(env): + # test that icon in LA mode can be used for buttons + # see GH#25164 + try: + # run inside subprocess for a self-contained environment + proc = subprocess_run_helper( + _test_toolbar_button_la_mode_icon_inside_subprocess, + timeout=_test_timeout, + extra_env=env, + ) + except subprocess.CalledProcessError as err: + pytest.fail( + f"subprocess failed to test intended behavior: {err.stderr}") From 6ff693a7880922fb715ea9d1ebdcb5fd68532246 Mon Sep 17 00:00:00 2001 From: Felix Goudreault Date: Wed, 8 Feb 2023 17:37:40 -0500 Subject: [PATCH 3/4] Fixed similar bug in wx backend. --- lib/matplotlib/backends/backend_wx.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/matplotlib/backends/backend_wx.py b/lib/matplotlib/backends/backend_wx.py index d41b98a47266..d4eef8e22705 100644 --- a/lib/matplotlib/backends/backend_wx.py +++ b/lib/matplotlib/backends/backend_wx.py @@ -1112,7 +1112,9 @@ def _icon(name): *name*, including the extension and relative to Matplotlib's "images" data directory. """ - image = np.array(PIL.Image.open(cbook._get_data_path("images", name))) + pilimg = PIL.Image.open(cbook._get_data_path("images", name)) + # ensure RGBA as wx BitMap expects RGBA format + image = np.array(pilimg.convert("RGBA")) try: dark = wx.SystemSettings.GetAppearance().IsDark() except AttributeError: # wxpython < 4.1 From 66a8dd5ef37c216809557455b0bdc3390ffef275 Mon Sep 17 00:00:00 2001 From: Felix Goudreault Date: Thu, 9 Feb 2023 10:56:10 -0500 Subject: [PATCH 4/4] Moved LA file mode for toolbar icon test in test_backends_interactive.py --- lib/matplotlib/tests/test_backend_tools.py | 51 +------------------ .../tests/test_backends_interactive.py | 43 +++++++++++++--- 2 files changed, 38 insertions(+), 56 deletions(-) diff --git a/lib/matplotlib/tests/test_backend_tools.py b/lib/matplotlib/tests/test_backend_tools.py index 2d37a9606a00..cc05a1a98f78 100644 --- a/lib/matplotlib/tests/test_backend_tools.py +++ b/lib/matplotlib/tests/test_backend_tools.py @@ -1,17 +1,6 @@ -import os -import subprocess -import tempfile -from PIL import Image - import pytest -import matplotlib -from matplotlib.backend_tools import ToolHelpBase, ToolToggleBase -import matplotlib.pyplot as plt -from matplotlib.testing import subprocess_run_helper -from .test_backends_interactive import ( - _get_testable_interactive_backends, _test_timeout, - ) +from matplotlib.backend_tools import ToolHelpBase @pytest.mark.parametrize('rc_shortcut,expected', [ @@ -29,41 +18,3 @@ ]) def test_format_shortcut(rc_shortcut, expected): assert ToolHelpBase.format_shortcut(rc_shortcut) == expected - - -def _test_toolbar_button_la_mode_icon_inside_subprocess(): - matplotlib.rcParams["toolbar"] = "toolmanager" - # create an icon in LA mode - with tempfile.TemporaryDirectory() as tempdir: - img = Image.new("LA", (26, 26)) - tmp_img_path = os.path.join(tempdir, "test_la_icon.png") - img.save(tmp_img_path) - - class CustomTool(ToolToggleBase): - image = tmp_img_path - description = "" # gtk3 backend does not allow None - - fig = plt.figure() - toolmanager = fig.canvas.manager.toolmanager - toolbar = fig.canvas.manager.toolbar - toolmanager.add_tool("test", CustomTool) - toolbar.add_tool("test", "group") - - -@pytest.mark.parametrize( - "env", - _get_testable_interactive_backends(), - ) -def test_toolbar_button_la_mode_icon(env): - # test that icon in LA mode can be used for buttons - # see GH#25164 - try: - # run inside subprocess for a self-contained environment - proc = subprocess_run_helper( - _test_toolbar_button_la_mode_icon_inside_subprocess, - timeout=_test_timeout, - extra_env=env, - ) - except subprocess.CalledProcessError as err: - pytest.fail( - f"subprocess failed to test intended behavior: {err.stderr}") diff --git a/lib/matplotlib/tests/test_backends_interactive.py b/lib/matplotlib/tests/test_backends_interactive.py index 498aa3b48c06..fa5566876919 100644 --- a/lib/matplotlib/tests/test_backends_interactive.py +++ b/lib/matplotlib/tests/test_backends_interactive.py @@ -7,13 +7,17 @@ import signal import subprocess import sys +import tempfile import time import urllib.request +from PIL import Image + import pytest import matplotlib as mpl from matplotlib import _c_internal_utils +from matplotlib.backend_tools import ToolToggleBase from matplotlib.testing import subprocess_run_helper as _run_helper @@ -71,6 +75,24 @@ def _get_testable_interactive_backends(): _test_timeout = 60 # A reasonably safe value for slower architectures. +def _test_toolbar_button_la_mode_icon(fig): + # test a toolbar button icon using an image in LA mode (GH issue 25174) + # create an icon in LA mode + with tempfile.TemporaryDirectory() as tempdir: + img = Image.new("LA", (26, 26)) + tmp_img_path = os.path.join(tempdir, "test_la_icon.png") + img.save(tmp_img_path) + + class CustomTool(ToolToggleBase): + image = tmp_img_path + description = "" # gtk3 backend does not allow None + + toolmanager = fig.canvas.manager.toolmanager + toolbar = fig.canvas.manager.toolbar + toolmanager.add_tool("test", CustomTool) + toolbar.add_tool("test", "group") + + # The source of this function gets extracted and run in another process, so it # must be fully self-contained. # Using a timer not only allows testing of timers (on other backends), but is @@ -122,7 +144,6 @@ def check_alt_backend(alt_backend): if importlib.util.find_spec("cairocffi"): check_alt_backend(backend[:-3] + "cairo") check_alt_backend("svg") - mpl.use(backend, force=True) fig, ax = plt.subplots() @@ -130,6 +151,10 @@ def check_alt_backend(alt_backend): type(fig.canvas).__module__, f"matplotlib.backends.backend_{backend}") + if mpl.rcParams["toolbar"] == "toolmanager": + # test toolbar button icon LA mode see GH issue 25174 + _test_toolbar_button_la_mode_icon(fig) + ax.plot([0, 1], [2, 3]) if fig.canvas.toolbar: # i.e toolbar2. fig.canvas.toolbar.draw_rubberband(None, 1., 1, 2., 2) @@ -168,11 +193,17 @@ def test_interactive_backend(env, toolbar): pytest.skip("toolmanager is not implemented for macosx.") if env["MPLBACKEND"] == "wx": pytest.skip("wx backend is deprecated; tests failed on appveyor") - proc = _run_helper(_test_interactive_impl, - json.dumps({"toolbar": toolbar}), - timeout=_test_timeout, - extra_env=env) - + try: + proc = _run_helper( + _test_interactive_impl, + json.dumps({"toolbar": toolbar}), + timeout=_test_timeout, + extra_env=env, + ) + except subprocess.CalledProcessError as err: + pytest.fail( + "Subprocess failed to test intended behavior\n" + + str(err.stderr)) assert proc.stdout.count("CloseEvent") == 1 pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy