diff --git a/lib/matplotlib/backends/registry.py b/lib/matplotlib/backends/registry.py index 47d5f65e350e..e08817bb089b 100644 --- a/lib/matplotlib/backends/registry.py +++ b/lib/matplotlib/backends/registry.py @@ -93,6 +93,9 @@ def __init__(self): } def _backend_module_name(self, backend): + if backend.startswith("module://"): + return backend[9:] + # Return name of module containing the specified backend. # Does not check if the backend is valid, use is_valid_backend for that. backend = backend.lower() @@ -224,7 +227,8 @@ def is_valid_backend(self, backend): bool True if backend is valid, False otherwise. """ - backend = backend.lower() + if not backend.startswith("module://"): + backend = backend.lower() # For backward compatibility, convert ipympl and matplotlib-inline long # module:// names to their shortened forms. @@ -342,7 +346,8 @@ def resolve_backend(self, backend): The GUI framework, which will be None for a backend that is non-interactive. """ if isinstance(backend, str): - backend = backend.lower() + if not backend.startswith("module://"): + backend = backend.lower() else: # Might be _auto_backend_sentinel or None # Use whatever is already running... from matplotlib import get_backend @@ -395,7 +400,8 @@ def resolve_gui_or_backend(self, gui_or_backend): framework : str or None The GUI framework, which will be None for a backend that is non-interactive. """ - gui_or_backend = gui_or_backend.lower() + if not gui_or_backend.startswith("module://"): + gui_or_backend = gui_or_backend.lower() # First check if it is a gui loop name. backend = self.backend_for_gui_framework(gui_or_backend) diff --git a/lib/matplotlib/tests/test_backend_registry.py b/lib/matplotlib/tests/test_backend_registry.py index 141ffd69c266..80c2ce4fc51a 100644 --- a/lib/matplotlib/tests/test_backend_registry.py +++ b/lib/matplotlib/tests/test_backend_registry.py @@ -86,6 +86,15 @@ def test_is_valid_backend(backend, is_valid): assert backend_registry.is_valid_backend(backend) == is_valid +@pytest.mark.parametrize("backend, normalized", [ + ("agg", "matplotlib.backends.backend_agg"), + ("QtAgg", "matplotlib.backends.backend_qtagg"), + ("module://Anything", "Anything"), +]) +def test_backend_normalization(backend, normalized): + assert backend_registry._backend_module_name(backend) == normalized + + def test_deprecated_rcsetup_attributes(): match = "was deprecated in Matplotlib 3.9" with pytest.warns(mpl.MatplotlibDeprecationWarning, match=match): diff --git a/lib/matplotlib/tests/test_backend_template.py b/lib/matplotlib/tests/test_backend_template.py index d7e2a5cd1266..964d15c1559a 100644 --- a/lib/matplotlib/tests/test_backend_template.py +++ b/lib/matplotlib/tests/test_backend_template.py @@ -49,3 +49,14 @@ def test_show_old_global_api(monkeypatch): mpl.use("module://mpl_test_backend") plt.show() mock_show.assert_called_with() + + +def test_load_case_sensitive(monkeypatch): + mpl_test_backend = SimpleNamespace(**vars(backend_template)) + 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()
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: