Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions galleries/examples/user_interfaces/mplcvd.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
===================================

To use this hook, ensure that this module is in your ``PYTHONPATH``, and set
``rcParams["figure.hooks"] = ["mplcvd:setup"]``. This hook depends on
the ``colorspacious`` third-party module.
``rcParams["figure.hooks"] = ["mplcvd:setup"]`` in your Python code. Note
that ``figure.hooks`` must be set programmatically and cannot be set from
``matplotlibrc`` or style files. This hook depends on the ``colorspacious``
third-party module.
"""

import functools
Expand Down
16 changes: 14 additions & 2 deletions lib/matplotlib/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -876,7 +876,8 @@ def _open_file_or_url(fname):
yield f


def _rc_params_in_file(fname, transform=lambda x: x, fail_on_error=False):
def _rc_params_in_file(fname, transform=lambda x: x, fail_on_error=False,
use_file_blacklist=True):
"""
Construct a `RcParams` instance from file *fname*.

Expand All @@ -892,6 +893,9 @@ def _rc_params_in_file(fname, transform=lambda x: x, fail_on_error=False):
before further parsing.
fail_on_error : bool, default: False
Whether invalid entries should result in an exception or a warning.
use_file_blacklist : bool, default: True
If True, filter out rcParams in `_RCPARAMS_FROM_FILE_BLACKLIST` that
should only be set programmatically (e.g. ``figure.hooks``).
"""
import matplotlib as mpl
rc_temp = {}
Expand Down Expand Up @@ -924,6 +928,13 @@ def _rc_params_in_file(fname, transform=lambda x: x, fail_on_error=False):
config = RcParams()

for key, (val, line, line_no) in rc_temp.items():
if use_file_blacklist and key in rcsetup._RCPARAMS_FROM_FILE_BLACKLIST:
_log.warning('%r is not supported in config files and will be '
'ignored; set it programmatically with '
'`matplotlib.rcParams[%r] = ...` instead. '
'(file %r, line %d)',
key, key, fname, line_no)
continue
if key in rcsetup._validators:
if fail_on_error:
config[key] = val # try to convert to proper type or raise
Expand Down Expand Up @@ -988,7 +999,8 @@ def rc_params_from_file(fname, fail_on_error=False, use_default_template=True):
cbook._get_data_path("matplotlibrc"),
# Strip leading comment.
transform=lambda line: line[1:] if line.startswith("#") else line,
fail_on_error=True)
fail_on_error=True,
use_file_blacklist=False)
rcParamsDefault._update_raw(rcsetup._hardcoded_defaults)
rcParamsDefault._ensure_has_backend()

Expand Down
3 changes: 2 additions & 1 deletion lib/matplotlib/mpl-data/matplotlibrc
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,8 @@
#backend_fallback: True

#interactive: False
#figure.hooks: # list of dotted.module.name:dotted.callable.name
#figure.hooks: # list of dotted.module.name:dotted.callable.name (must be set
# programmatically; ignored if set in this file or a style file)
#toolbar: toolbar2 # {None, toolbar2, toolmanager}
#timezone: UTC # a pytz timezone string, e.g., US/Central or Europe/Paris

Expand Down
4 changes: 4 additions & 0 deletions lib/matplotlib/rcsetup.py
Original file line number Diff line number Diff line change
Expand Up @@ -1445,6 +1445,10 @@ def _convert_validator_spec(key, conv):
_validators = {k: _convert_validator_spec(k, conv)
for k, conv in _validators.items()}

# rcParams that can execute arbitrary code and should only be set
# programmatically, never loaded from config files.
_RCPARAMS_FROM_FILE_BLACKLIST = {'figure.hooks'}


@dataclass
class _Param:
Expand Down
3 changes: 2 additions & 1 deletion lib/matplotlib/style/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@
'webagg.port_retries', 'webagg.open_in_browser', 'backend_fallback',
'toolbar', 'timezone', 'figure.max_open_warning',
'figure.raise_window', 'savefig.directory', 'tk.window_focus',
'docstring.hardcopy', 'date.epoch'}
'docstring.hardcopy', 'date.epoch',
'figure.hooks'}


@_docstring.Substitution(
Expand Down
14 changes: 14 additions & 0 deletions lib/matplotlib/tests/test_rcparams.py
Original file line number Diff line number Diff line change
Expand Up @@ -657,6 +657,20 @@ def test_rcparams_path_sketch_from_file(tmp_path, value):
assert mpl.rcParams["path.sketch"] == (1, 2, 3)


def test_file_blacklist(tmp_path, caplog):
"""Blacklisted rcParams should be ignored with a warning when loaded."""
rc_path = tmp_path / "matplotlibrc"
rc_path.write_text("figure.hooks: my_module:my_func\nlines.linewidth: 42")

with caplog.at_level("WARNING", logger="matplotlib"):
with mpl.rc_context(fname=rc_path):
# Blacklisted param should be unchanged (default is []).
assert mpl.rcParams["figure.hooks"] == []
# Non-blacklisted param should load normally.
assert mpl.rcParams["lines.linewidth"] == 42
assert "not supported in config files" in caplog.text


@pytest.mark.parametrize('group, option, alias, value', [
('lines', 'linewidth', 'lw', 3),
('lines', 'linestyle', 'ls', 'dashed'),
Expand Down
Loading