From ab677a820f5269f471fd763e6bdc8647859d7216 Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Fri, 20 Sep 2019 03:13:46 +0200 Subject: [PATCH 1/2] Simplify the rcparams deprecation machinery. Just have a single kind of deprecated rcParams, which emit a DeprecationWarning on get and on set. ... which caught the fact that we were previously *not* warning on access to text.latex.unicode, now we do but need to avoid triggering the warnings internally. --- lib/matplotlib/__init__.py | 78 ++++++--------------------- lib/matplotlib/tests/test_rcparams.py | 3 +- lib/matplotlib/texmanager.py | 7 +-- 3 files changed, 22 insertions(+), 66 deletions(-) diff --git a/lib/matplotlib/__init__.py b/lib/matplotlib/__init__.py index 48db8d1d111c..79bd6e0f4f24 100644 --- a/lib/matplotlib/__init__.py +++ b/lib/matplotlib/__init__.py @@ -604,25 +604,12 @@ def gen_candidates(): "install is broken") -# rcParams deprecated and automatically mapped to another key. -# Values are tuples of (version, new_name, f_old2new, f_new2old). -_deprecated_map = {} - -# rcParams deprecated; some can manually be mapped to another key. -# Values are tuples of (version, new_name_or_None). -_deprecated_ignore_map = { -} - -# rcParams deprecated; can use None to suppress warnings; remain actually -# listed in the rcParams (not included in _all_deprecated). -# Values are tuples of (version,) -_deprecated_remain_as_none = { +# Deprecated rcParams, with kwargs to warn_deprecated. Must at least specify +# the 'since' key. +_deprecated_rcs = { } -_all_deprecated = {*_deprecated_map, *_deprecated_ignore_map} - - class RcParams(MutableMapping, dict): """ A dictionary object including validation. @@ -636,34 +623,20 @@ class RcParams(MutableMapping, dict): """ validate = {key: converter - for key, (default, converter) in defaultParams.items() - if key not in _all_deprecated} + for key, (default, converter) in defaultParams.items()} # validate values on the way in def __init__(self, *args, **kwargs): self.update(*args, **kwargs) def __setitem__(self, key, val): + if (key == 'backend' and val is rcsetup._auto_backend_sentinel + and 'backend' in self): + return + if key in _deprecated_rcs: + cbook.warn_deprecated( + **{"name": key, "obj_type": "rcparam", **_deprecated_rcs[key]}) try: - if key in _deprecated_map: - version, alt_key, alt_val, inverse_alt = _deprecated_map[key] - cbook.warn_deprecated( - version, name=key, obj_type="rcparam", alternative=alt_key) - key = alt_key - val = alt_val(val) - elif key in _deprecated_remain_as_none and val is not None: - version, = _deprecated_remain_as_none[key] - cbook.warn_deprecated( - version, name=key, obj_type="rcparam") - elif key in _deprecated_ignore_map: - version, alt_key = _deprecated_ignore_map[key] - cbook.warn_deprecated( - version, name=key, obj_type="rcparam", alternative=alt_key) - return - elif key == 'backend': - if val is rcsetup._auto_backend_sentinel: - if 'backend' in self: - return try: cval = self.validate[key](val) except ValueError as ve: @@ -675,24 +648,14 @@ def __setitem__(self, key, val): f"a list of valid parameters)") def __getitem__(self, key): - if key in _deprecated_map: - version, alt_key, alt_val, inverse_alt = _deprecated_map[key] - cbook.warn_deprecated( - version, name=key, obj_type="rcparam", alternative=alt_key) - return inverse_alt(dict.__getitem__(self, alt_key)) - - elif key in _deprecated_ignore_map: - version, alt_key = _deprecated_ignore_map[key] - cbook.warn_deprecated( - version, name=key, obj_type="rcparam", alternative=alt_key) - return dict.__getitem__(self, alt_key) if alt_key else None - - elif key == "backend": + if key == "backend": val = dict.__getitem__(self, key) if val is rcsetup._auto_backend_sentinel: from matplotlib import pyplot as plt plt.switch_backend(rcsetup._auto_backend_sentinel) - + if key in _deprecated_rcs: + cbook.warn_deprecated( + **{"name": key, "obj_type": "rcparam", **_deprecated_rcs[key]}) return dict.__getitem__(self, key) def __repr__(self): @@ -812,11 +775,6 @@ def _rc_params_in_file(fname, fail_on_error=False): error_details = _error_details_fmt % (line_no, line, fname) _log.warning('Bad val %r on %s\n\t%s', val, error_details, msg) - elif key in _deprecated_ignore_map: - version, alt_key = _deprecated_ignore_map[key] - cbook.warn_deprecated( - version, name=key, alternative=alt_key, - addendum="Please update your matplotlibrc.") else: version = 'master' if '.post' in __version__ else f'v{__version__}' print(f""" @@ -850,8 +808,7 @@ def rc_params_from_file(fname, fail_on_error=False, use_default_template=True): iter_params = defaultParams.items() with cbook._suppress_matplotlib_deprecation_warning(): - config = RcParams([(key, default) for key, (default, _) in iter_params - if key not in _all_deprecated]) + config = RcParams((key, default) for key, (default, _) in iter_params) config.update(config_from_file) if config['datapath'] is None: @@ -876,9 +833,8 @@ def rc_params_from_file(fname, fail_on_error=False, use_default_template=True): with cbook._suppress_matplotlib_deprecation_warning(): rcParamsOrig = RcParams(rcParams.copy()) - rcParamsDefault = RcParams([(key, default) for key, (default, converter) in - defaultParams.items() - if key not in _all_deprecated]) + rcParamsDefault = RcParams( + (key, default) for key, (default, converter) in defaultParams.items()) if rcParams['axes.formatter.use_locale']: locale.setlocale(locale.LC_ALL, '') diff --git a/lib/matplotlib/tests/test_rcparams.py b/lib/matplotlib/tests/test_rcparams.py index 4b4da484c010..b4f56071ef33 100644 --- a/lib/matplotlib/tests/test_rcparams.py +++ b/lib/matplotlib/tests/test_rcparams.py @@ -465,14 +465,13 @@ def test_rcparams_reset_after_fail(): def test_if_rctemplate_is_up_to_date(): # This tests if the matplotlibrc.template file contains all valid rcParams. - deprecated = {*mpl._all_deprecated, *mpl._deprecated_remain_as_none} with cbook._get_data_path('matplotlibrc').open() as file: rclines = file.readlines() missing = {} for k, v in mpl.defaultParams.items(): if k[0] == "_": continue - if k in deprecated: + if k in mpl._deprecated_rcs: continue found = False for line in rclines: diff --git a/lib/matplotlib/texmanager.py b/lib/matplotlib/texmanager.py index fb23212febf8..8a9fe8353485 100644 --- a/lib/matplotlib/texmanager.py +++ b/lib/matplotlib/texmanager.py @@ -160,14 +160,15 @@ def get_font_config(self): if self._rc_cache is None: self._rc_cache = dict.fromkeys(self._rc_cache_keys) changed = [par for par in self._rc_cache_keys - if rcParams[par] != self._rc_cache[par]] + if dict.__getitem__(rcParams, par) != self._rc_cache[par]] if changed: _log.debug('following keys changed: %s', changed) for k in changed: _log.debug('%-20s: %-10s -> %-10s', - k, self._rc_cache[k], rcParams[k]) + k, self._rc_cache[k], dict.__getitem__(rcParams, k)) # deepcopy may not be necessary, but feels more future-proof - self._rc_cache[k] = copy.deepcopy(rcParams[k]) + self._rc_cache[k] = copy.deepcopy( + dict.__getitem__(rcParams, k)) _log.debug('RE-INIT\nold fontconfig: %s', self._fontconfig) self._reinit() _log.debug('fontconfig: %s', self._fontconfig) From 7350d8be5f1f6828843a3f5529724087d8ae7de5 Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Sun, 24 Nov 2019 20:35:25 +0100 Subject: [PATCH 2/2] Add rcParams._getitem_skip_deprecation. --- lib/matplotlib/__init__.py | 9 ++++++--- lib/matplotlib/texmanager.py | 8 +++++--- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/lib/matplotlib/__init__.py b/lib/matplotlib/__init__.py index 79bd6e0f4f24..0bada8fc041e 100644 --- a/lib/matplotlib/__init__.py +++ b/lib/matplotlib/__init__.py @@ -648,14 +648,17 @@ def __setitem__(self, key, val): f"a list of valid parameters)") def __getitem__(self, key): + if key in _deprecated_rcs: + cbook.warn_deprecated( + **{"name": key, "obj_type": "rcparam", **_deprecated_rcs[key]}) + return self._getitem_skip_deprecation(key) + + def _getitem_skip_deprecation(self, key): if key == "backend": val = dict.__getitem__(self, key) if val is rcsetup._auto_backend_sentinel: from matplotlib import pyplot as plt plt.switch_backend(rcsetup._auto_backend_sentinel) - if key in _deprecated_rcs: - cbook.warn_deprecated( - **{"name": key, "obj_type": "rcparam", **_deprecated_rcs[key]}) return dict.__getitem__(self, key) def __repr__(self): diff --git a/lib/matplotlib/texmanager.py b/lib/matplotlib/texmanager.py index 8a9fe8353485..a267b1113303 100644 --- a/lib/matplotlib/texmanager.py +++ b/lib/matplotlib/texmanager.py @@ -160,15 +160,17 @@ def get_font_config(self): if self._rc_cache is None: self._rc_cache = dict.fromkeys(self._rc_cache_keys) changed = [par for par in self._rc_cache_keys - if dict.__getitem__(rcParams, par) != self._rc_cache[par]] + if (rcParams._getitem_skip_deprecation(par) + != self._rc_cache[par])] if changed: _log.debug('following keys changed: %s', changed) for k in changed: _log.debug('%-20s: %-10s -> %-10s', - k, self._rc_cache[k], dict.__getitem__(rcParams, k)) + k, self._rc_cache[k], + rcParams._getitem_skip_deprecation(k)) # deepcopy may not be necessary, but feels more future-proof self._rc_cache[k] = copy.deepcopy( - dict.__getitem__(rcParams, k)) + rcParams._getitem_skip_deprecation(k)) _log.debug('RE-INIT\nold fontconfig: %s', self._fontconfig) self._reinit() _log.debug('fontconfig: %s', self._fontconfig)