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.
		
		
		
		
		
			
		
			
				
	
	
		
			198 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			Python
		
	
			
		
		
	
	
			198 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			Python
		
	
from contextlib import contextmanager
 | 
						|
from pathlib import Path
 | 
						|
from tempfile import TemporaryDirectory
 | 
						|
import sys
 | 
						|
 | 
						|
import numpy as np
 | 
						|
import pytest
 | 
						|
 | 
						|
import matplotlib as mpl
 | 
						|
from matplotlib import pyplot as plt, style
 | 
						|
from matplotlib.style.core import USER_LIBRARY_PATHS, STYLE_EXTENSION
 | 
						|
 | 
						|
 | 
						|
PARAM = 'image.cmap'
 | 
						|
VALUE = 'pink'
 | 
						|
DUMMY_SETTINGS = {PARAM: VALUE}
 | 
						|
 | 
						|
 | 
						|
@contextmanager
 | 
						|
def temp_style(style_name, settings=None):
 | 
						|
    """Context manager to create a style sheet in a temporary directory."""
 | 
						|
    if not settings:
 | 
						|
        settings = DUMMY_SETTINGS
 | 
						|
    temp_file = f'{style_name}.{STYLE_EXTENSION}'
 | 
						|
    try:
 | 
						|
        with TemporaryDirectory() as tmpdir:
 | 
						|
            # Write style settings to file in the tmpdir.
 | 
						|
            Path(tmpdir, temp_file).write_text(
 | 
						|
                "\n".join(f"{k}: {v}" for k, v in settings.items()),
 | 
						|
                encoding="utf-8")
 | 
						|
            # Add tmpdir to style path and reload so we can access this style.
 | 
						|
            USER_LIBRARY_PATHS.append(tmpdir)
 | 
						|
            style.reload_library()
 | 
						|
            yield
 | 
						|
    finally:
 | 
						|
        style.reload_library()
 | 
						|
 | 
						|
 | 
						|
def test_invalid_rc_warning_includes_filename(caplog):
 | 
						|
    SETTINGS = {'foo': 'bar'}
 | 
						|
    basename = 'basename'
 | 
						|
    with temp_style(basename, SETTINGS):
 | 
						|
        # style.reload_library() in temp_style() triggers the warning
 | 
						|
        pass
 | 
						|
    assert (len(caplog.records) == 1
 | 
						|
            and basename in caplog.records[0].getMessage())
 | 
						|
 | 
						|
 | 
						|
def test_available():
 | 
						|
    with temp_style('_test_', DUMMY_SETTINGS):
 | 
						|
        assert '_test_' in style.available
 | 
						|
 | 
						|
 | 
						|
def test_use():
 | 
						|
    mpl.rcParams[PARAM] = 'gray'
 | 
						|
    with temp_style('test', DUMMY_SETTINGS):
 | 
						|
        with style.context('test'):
 | 
						|
            assert mpl.rcParams[PARAM] == VALUE
 | 
						|
 | 
						|
 | 
						|
def test_use_url(tmp_path):
 | 
						|
    path = tmp_path / 'file'
 | 
						|
    path.write_text('axes.facecolor: adeade', encoding='utf-8')
 | 
						|
    with temp_style('test', DUMMY_SETTINGS):
 | 
						|
        url = ('file:'
 | 
						|
               + ('///' if sys.platform == 'win32' else '')
 | 
						|
               + path.resolve().as_posix())
 | 
						|
        with style.context(url):
 | 
						|
            assert mpl.rcParams['axes.facecolor'] == "#adeade"
 | 
						|
 | 
						|
 | 
						|
def test_single_path(tmp_path):
 | 
						|
    mpl.rcParams[PARAM] = 'gray'
 | 
						|
    path = tmp_path / f'text.{STYLE_EXTENSION}'
 | 
						|
    path.write_text(f'{PARAM} : {VALUE}', encoding='utf-8')
 | 
						|
    with style.context(path):
 | 
						|
        assert mpl.rcParams[PARAM] == VALUE
 | 
						|
    assert mpl.rcParams[PARAM] == 'gray'
 | 
						|
 | 
						|
 | 
						|
def test_context():
 | 
						|
    mpl.rcParams[PARAM] = 'gray'
 | 
						|
    with temp_style('test', DUMMY_SETTINGS):
 | 
						|
        with style.context('test'):
 | 
						|
            assert mpl.rcParams[PARAM] == VALUE
 | 
						|
    # Check that this value is reset after the exiting the context.
 | 
						|
    assert mpl.rcParams[PARAM] == 'gray'
 | 
						|
 | 
						|
 | 
						|
def test_context_with_dict():
 | 
						|
    original_value = 'gray'
 | 
						|
    other_value = 'blue'
 | 
						|
    mpl.rcParams[PARAM] = original_value
 | 
						|
    with style.context({PARAM: other_value}):
 | 
						|
        assert mpl.rcParams[PARAM] == other_value
 | 
						|
    assert mpl.rcParams[PARAM] == original_value
 | 
						|
 | 
						|
 | 
						|
def test_context_with_dict_after_namedstyle():
 | 
						|
    # Test dict after style name where dict modifies the same parameter.
 | 
						|
    original_value = 'gray'
 | 
						|
    other_value = 'blue'
 | 
						|
    mpl.rcParams[PARAM] = original_value
 | 
						|
    with temp_style('test', DUMMY_SETTINGS):
 | 
						|
        with style.context(['test', {PARAM: other_value}]):
 | 
						|
            assert mpl.rcParams[PARAM] == other_value
 | 
						|
    assert mpl.rcParams[PARAM] == original_value
 | 
						|
 | 
						|
 | 
						|
def test_context_with_dict_before_namedstyle():
 | 
						|
    # Test dict before style name where dict modifies the same parameter.
 | 
						|
    original_value = 'gray'
 | 
						|
    other_value = 'blue'
 | 
						|
    mpl.rcParams[PARAM] = original_value
 | 
						|
    with temp_style('test', DUMMY_SETTINGS):
 | 
						|
        with style.context([{PARAM: other_value}, 'test']):
 | 
						|
            assert mpl.rcParams[PARAM] == VALUE
 | 
						|
    assert mpl.rcParams[PARAM] == original_value
 | 
						|
 | 
						|
 | 
						|
def test_context_with_union_of_dict_and_namedstyle():
 | 
						|
    # Test dict after style name where dict modifies the a different parameter.
 | 
						|
    original_value = 'gray'
 | 
						|
    other_param = 'text.usetex'
 | 
						|
    other_value = True
 | 
						|
    d = {other_param: other_value}
 | 
						|
    mpl.rcParams[PARAM] = original_value
 | 
						|
    mpl.rcParams[other_param] = (not other_value)
 | 
						|
    with temp_style('test', DUMMY_SETTINGS):
 | 
						|
        with style.context(['test', d]):
 | 
						|
            assert mpl.rcParams[PARAM] == VALUE
 | 
						|
            assert mpl.rcParams[other_param] == other_value
 | 
						|
    assert mpl.rcParams[PARAM] == original_value
 | 
						|
    assert mpl.rcParams[other_param] == (not other_value)
 | 
						|
 | 
						|
 | 
						|
def test_context_with_badparam():
 | 
						|
    original_value = 'gray'
 | 
						|
    other_value = 'blue'
 | 
						|
    with style.context({PARAM: other_value}):
 | 
						|
        assert mpl.rcParams[PARAM] == other_value
 | 
						|
        x = style.context({PARAM: original_value, 'badparam': None})
 | 
						|
        with pytest.raises(KeyError):
 | 
						|
            with x:
 | 
						|
                pass
 | 
						|
        assert mpl.rcParams[PARAM] == other_value
 | 
						|
 | 
						|
 | 
						|
@pytest.mark.parametrize('equiv_styles',
 | 
						|
                         [('mpl20', 'default'),
 | 
						|
                          ('mpl15', 'classic')],
 | 
						|
                         ids=['mpl20', 'mpl15'])
 | 
						|
def test_alias(equiv_styles):
 | 
						|
    rc_dicts = []
 | 
						|
    for sty in equiv_styles:
 | 
						|
        with style.context(sty):
 | 
						|
            rc_dicts.append(mpl.rcParams.copy())
 | 
						|
 | 
						|
    rc_base = rc_dicts[0]
 | 
						|
    for nm, rc in zip(equiv_styles[1:], rc_dicts[1:]):
 | 
						|
        assert rc_base == rc
 | 
						|
 | 
						|
 | 
						|
def test_xkcd_no_cm():
 | 
						|
    assert mpl.rcParams["path.sketch"] is None
 | 
						|
    plt.xkcd()
 | 
						|
    assert mpl.rcParams["path.sketch"] == (1, 100, 2)
 | 
						|
    np.testing.break_cycles()
 | 
						|
    assert mpl.rcParams["path.sketch"] == (1, 100, 2)
 | 
						|
 | 
						|
 | 
						|
def test_xkcd_cm():
 | 
						|
    assert mpl.rcParams["path.sketch"] is None
 | 
						|
    with plt.xkcd():
 | 
						|
        assert mpl.rcParams["path.sketch"] == (1, 100, 2)
 | 
						|
    assert mpl.rcParams["path.sketch"] is None
 | 
						|
 | 
						|
 | 
						|
def test_up_to_date_blacklist():
 | 
						|
    assert mpl.style.core.STYLE_BLACKLIST <= {*mpl.rcsetup._validators}
 | 
						|
 | 
						|
 | 
						|
def test_style_from_module(tmp_path, monkeypatch):
 | 
						|
    monkeypatch.syspath_prepend(tmp_path)
 | 
						|
    monkeypatch.chdir(tmp_path)
 | 
						|
    pkg_path = tmp_path / "mpl_test_style_pkg"
 | 
						|
    pkg_path.mkdir()
 | 
						|
    (pkg_path / "test_style.mplstyle").write_text(
 | 
						|
        "lines.linewidth: 42", encoding="utf-8")
 | 
						|
    pkg_path.with_suffix(".mplstyle").write_text(
 | 
						|
        "lines.linewidth: 84", encoding="utf-8")
 | 
						|
    mpl.style.use("mpl_test_style_pkg.test_style")
 | 
						|
    assert mpl.rcParams["lines.linewidth"] == 42
 | 
						|
    mpl.style.use("mpl_test_style_pkg.mplstyle")
 | 
						|
    assert mpl.rcParams["lines.linewidth"] == 84
 | 
						|
    mpl.style.use("./mpl_test_style_pkg.mplstyle")
 | 
						|
    assert mpl.rcParams["lines.linewidth"] == 84
 |