You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			181 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			Python
		
	
			
		
		
	
	
			181 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			Python
		
	
from collections.abc import Sequence
 | 
						|
from typing import Any
 | 
						|
 | 
						|
import pytest
 | 
						|
 | 
						|
import matplotlib as mpl
 | 
						|
from matplotlib.backends import BackendFilter, backend_registry
 | 
						|
 | 
						|
 | 
						|
@pytest.fixture
 | 
						|
def clear_backend_registry():
 | 
						|
    # Fixture that clears the singleton backend_registry before and after use
 | 
						|
    # so that the test state remains isolated.
 | 
						|
    backend_registry._clear()
 | 
						|
    yield
 | 
						|
    backend_registry._clear()
 | 
						|
 | 
						|
 | 
						|
def has_duplicates(seq: Sequence[Any]) -> bool:
 | 
						|
    return len(seq) > len(set(seq))
 | 
						|
 | 
						|
 | 
						|
@pytest.mark.parametrize(
 | 
						|
    'framework,expected',
 | 
						|
    [
 | 
						|
        ('qt', 'qtagg'),
 | 
						|
        ('gtk3', 'gtk3agg'),
 | 
						|
        ('gtk4', 'gtk4agg'),
 | 
						|
        ('wx', 'wxagg'),
 | 
						|
        ('tk', 'tkagg'),
 | 
						|
        ('macosx', 'macosx'),
 | 
						|
        ('headless', 'agg'),
 | 
						|
        ('does not exist', None),
 | 
						|
    ]
 | 
						|
)
 | 
						|
def test_backend_for_gui_framework(framework, expected):
 | 
						|
    assert backend_registry.backend_for_gui_framework(framework) == expected
 | 
						|
 | 
						|
 | 
						|
def test_list_builtin():
 | 
						|
    backends = backend_registry.list_builtin()
 | 
						|
    assert not has_duplicates(backends)
 | 
						|
    # Compare using sets as order is not important
 | 
						|
    assert {*backends} == {
 | 
						|
        'gtk3agg', 'gtk3cairo', 'gtk4agg', 'gtk4cairo', 'macosx', 'nbagg', 'notebook',
 | 
						|
        'qtagg', 'qtcairo', 'qt5agg', 'qt5cairo', 'tkagg',
 | 
						|
        'tkcairo', 'webagg', 'wx', 'wxagg', 'wxcairo', 'agg', 'cairo', 'pdf', 'pgf',
 | 
						|
        'ps', 'svg', 'template',
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
@pytest.mark.parametrize(
 | 
						|
    'filter,expected',
 | 
						|
    [
 | 
						|
        (BackendFilter.INTERACTIVE,
 | 
						|
         ['gtk3agg', 'gtk3cairo', 'gtk4agg', 'gtk4cairo', 'macosx', 'nbagg', 'notebook',
 | 
						|
          'qtagg', 'qtcairo', 'qt5agg', 'qt5cairo', 'tkagg',
 | 
						|
          'tkcairo', 'webagg', 'wx', 'wxagg', 'wxcairo']),
 | 
						|
        (BackendFilter.NON_INTERACTIVE,
 | 
						|
         ['agg', 'cairo', 'pdf', 'pgf', 'ps', 'svg', 'template']),
 | 
						|
    ]
 | 
						|
)
 | 
						|
def test_list_builtin_with_filter(filter, expected):
 | 
						|
    backends = backend_registry.list_builtin(filter)
 | 
						|
    assert not has_duplicates(backends)
 | 
						|
    # Compare using sets as order is not important
 | 
						|
    assert {*backends} == {*expected}
 | 
						|
 | 
						|
 | 
						|
def test_list_gui_frameworks():
 | 
						|
    frameworks = backend_registry.list_gui_frameworks()
 | 
						|
    assert not has_duplicates(frameworks)
 | 
						|
    # Compare using sets as order is not important
 | 
						|
    assert {*frameworks} == {
 | 
						|
        "gtk3", "gtk4", "macosx", "qt", "qt5", "qt6", "tk", "wx",
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
@pytest.mark.parametrize("backend, is_valid", [
 | 
						|
    ("agg", True),
 | 
						|
    ("QtAgg", True),
 | 
						|
    ("module://anything", True),
 | 
						|
    ("made-up-name", False),
 | 
						|
])
 | 
						|
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):
 | 
						|
        mpl.rcsetup.interactive_bk
 | 
						|
    with pytest.warns(mpl.MatplotlibDeprecationWarning, match=match):
 | 
						|
        mpl.rcsetup.non_interactive_bk
 | 
						|
    with pytest.warns(mpl.MatplotlibDeprecationWarning, match=match):
 | 
						|
        mpl.rcsetup.all_backends
 | 
						|
 | 
						|
 | 
						|
def test_entry_points_inline():
 | 
						|
    pytest.importorskip('matplotlib_inline')
 | 
						|
    backends = backend_registry.list_all()
 | 
						|
    assert 'inline' in backends
 | 
						|
 | 
						|
 | 
						|
def test_entry_points_ipympl():
 | 
						|
    pytest.importorskip('ipympl')
 | 
						|
    backends = backend_registry.list_all()
 | 
						|
    assert 'ipympl' in backends
 | 
						|
    assert 'widget' in backends
 | 
						|
 | 
						|
 | 
						|
def test_entry_point_name_shadows_builtin(clear_backend_registry):
 | 
						|
    with pytest.raises(RuntimeError):
 | 
						|
        backend_registry._validate_and_store_entry_points(
 | 
						|
            [('qtagg', 'module1')])
 | 
						|
 | 
						|
 | 
						|
def test_entry_point_name_duplicate(clear_backend_registry):
 | 
						|
    with pytest.raises(RuntimeError):
 | 
						|
        backend_registry._validate_and_store_entry_points(
 | 
						|
            [('some_name', 'module1'), ('some_name', 'module2')])
 | 
						|
 | 
						|
 | 
						|
def test_entry_point_identical(clear_backend_registry):
 | 
						|
    # Issue https://github.com/matplotlib/matplotlib/issues/28367
 | 
						|
    # Multiple entry points with the same name and value (value is the module)
 | 
						|
    # are acceptable.
 | 
						|
    n = len(backend_registry._name_to_module)
 | 
						|
    backend_registry._validate_and_store_entry_points(
 | 
						|
        [('some_name', 'some.module'), ('some_name', 'some.module')])
 | 
						|
    assert len(backend_registry._name_to_module) == n+1
 | 
						|
    assert backend_registry._name_to_module['some_name'] == 'module://some.module'
 | 
						|
 | 
						|
 | 
						|
def test_entry_point_name_is_module(clear_backend_registry):
 | 
						|
    with pytest.raises(RuntimeError):
 | 
						|
        backend_registry._validate_and_store_entry_points(
 | 
						|
            [('module://backend.something', 'module1')])
 | 
						|
 | 
						|
 | 
						|
@pytest.mark.parametrize('backend', [
 | 
						|
    'agg',
 | 
						|
    'module://matplotlib.backends.backend_agg',
 | 
						|
])
 | 
						|
def test_load_entry_points_only_if_needed(clear_backend_registry, backend):
 | 
						|
    assert not backend_registry._loaded_entry_points
 | 
						|
    check = backend_registry.resolve_backend(backend)
 | 
						|
    assert check == (backend, None)
 | 
						|
    assert not backend_registry._loaded_entry_points
 | 
						|
    backend_registry.list_all()  # Force load of entry points
 | 
						|
    assert backend_registry._loaded_entry_points
 | 
						|
 | 
						|
 | 
						|
@pytest.mark.parametrize(
 | 
						|
    'gui_or_backend, expected_backend, expected_gui',
 | 
						|
    [
 | 
						|
        ('agg', 'agg', None),
 | 
						|
        ('qt', 'qtagg', 'qt'),
 | 
						|
        ('TkCairo', 'tkcairo', 'tk'),
 | 
						|
    ]
 | 
						|
)
 | 
						|
def test_resolve_gui_or_backend(gui_or_backend, expected_backend, expected_gui):
 | 
						|
    backend, gui = backend_registry.resolve_gui_or_backend(gui_or_backend)
 | 
						|
    assert backend == expected_backend
 | 
						|
    assert gui == expected_gui
 | 
						|
 | 
						|
 | 
						|
def test_resolve_gui_or_backend_invalid():
 | 
						|
    match = "is not a recognised GUI loop or backend name"
 | 
						|
    with pytest.raises(RuntimeError, match=match):
 | 
						|
        backend_registry.resolve_gui_or_backend('no-such-name')
 |