diff --git a/doc/api/next_api_changes/2018-02-15-AL-deprecations.rst b/doc/api/next_api_changes/2018-02-15-AL-deprecations.rst index 5d799c5587ec..df34bd47dab4 100644 --- a/doc/api/next_api_changes/2018-02-15-AL-deprecations.rst +++ b/doc/api/next_api_changes/2018-02-15-AL-deprecations.rst @@ -10,6 +10,9 @@ The following modules are deprecated: The following classes, methods, functions, and attributes are deprecated: +- ``RcParams.msg_depr``, ``RcParams.msg_depr_ignore``, + ``RcParams.msg_depr_set``, ``RcParams.msg_obsolete``, + ``RcParams.msg_backend_obsolete``, - ``afm.parse_afm``, - ``backend_pgf.get_texcommand``, - ``backend_ps.get_bbox``, diff --git a/lib/matplotlib/__init__.py b/lib/matplotlib/__init__.py index 2019eebfe8cb..52205228271e 100644 --- a/lib/matplotlib/__init__.py +++ b/lib/matplotlib/__init__.py @@ -123,11 +123,11 @@ import importlib import inspect from inspect import Parameter -import itertools import locale import logging import os from pathlib import Path +import pprint import re import shutil import stat @@ -800,23 +800,29 @@ def gen_candidates(): return fname -# names of keys to deprecate -# the values are a tuple of (new_name, f_old_2_new, f_new_2_old) -# the inverse function may be `None` +# rcParams deprecated and automatically mapped to another key. +# Values are tuples of (version, new_name, f_old2new, f_new2old). _deprecated_map = {} -_deprecated_ignore_map = {'nbagg.transparent': 'figure.facecolor'} +# rcParams deprecated; some can manually be mapped to another key. +# Values are tuples of (version, new_name_or_None). +_deprecated_ignore_map = { + 'text.dvipnghack': ('2.1', None), + 'nbagg.transparent': ('2.2', 'figure.facecolor'), + 'plugins.directory': ('2.2', None), + 'pgf.debug': ('3.0', None), +} -_obsolete_set = {'pgf.debug', 'plugins.directory', 'text.dvipnghack'} +# rcParams deprecated; can use None to suppress warnings; remain actually +# listed in the rcParams (not included in _all_deprecated). +# Values are typles of (version,) +_deprecated_remain_as_none = { + 'axes.hold': ('2.1',), + 'backend.qt4': ('2.2',), + 'backend.qt5': ('2.2',), +} -# The following may use a value of None to suppress the warning. -# do NOT include in _all_deprecated -_deprecated_set = {'axes.hold', - 'backend.qt4', - 'backend.qt5'} - -_all_deprecated = set(itertools.chain( - _deprecated_ignore_map, _deprecated_map, _obsolete_set)) +_all_deprecated = {*_deprecated_map, *_deprecated_ignore_map} class RcParams(MutableMapping, dict): @@ -831,16 +837,35 @@ class RcParams(MutableMapping, dict): validate = {key: converter for key, (default, converter) in defaultParams.items() if key not in _all_deprecated} - msg_depr = "%s is deprecated and replaced with %s; please use the latter." - msg_depr_set = ("%s is deprecated. Please remove it from your " - "matplotlibrc and/or style files.") - msg_depr_ignore = "%s is deprecated and ignored. Use %s instead." - msg_obsolete = ("%s is obsolete. Please remove it from your matplotlibrc " - "and/or style files.") - msg_backend_obsolete = ("The {} rcParam was deprecated in version 2.2. In" - " order to force the use of a specific Qt binding," - " either import that binding first, or set the " - "QT_API environment variable.") + + @property + @cbook.deprecated("3.0") + def msg_depr(self): + return "%s is deprecated and replaced with %s; please use the latter." + + @property + @cbook.deprecated("3.0") + def msg_depr_ignore(self): + return "%s is deprecated and ignored. Use %s instead." + + @property + @cbook.deprecated("3.0") + def msg_depr_set(self): + return ("%s is deprecated. Please remove it from your matplotlibrc " + "and/or style files.") + + @property + @cbook.deprecated("3.0") + def msg_obsolete(self): + return ("%s is obsolete. Please remove it from your matplotlibrc " + "and/or style files.") + + @property + @cbook.deprecated("3.0") + def msg_backend_obsolete(self): + return ("The {} rcParam was deprecated in version 2.2. In order to " + "force the use of a specific Qt binding, either import that " + "binding first, or set the QT_API environment variable.") # validate values on the way in def __init__(self, *args, **kwargs): @@ -849,26 +874,25 @@ def __init__(self, *args, **kwargs): def __setitem__(self, key, val): try: if key in _deprecated_map: - alt_key, alt_val, inverse_alt = _deprecated_map[key] - warnings.warn(self.msg_depr % (key, alt_key), - mplDeprecation) + version, alt_key, alt_val, inverse_alt = _deprecated_map[key] + cbook.warn_deprecated( + version, key, obj_type="rcparam", alternative=alt_key) key = alt_key val = alt_val(val) - elif key in _deprecated_set and val is not None: + elif key in _deprecated_remain_as_none and val is not None: + version, = _deprecated_remain_as_none[key] + addendum = None if key.startswith('backend'): - warnings.warn(self.msg_backend_obsolete.format(key), - mplDeprecation) - else: - warnings.warn(self.msg_depr_set % key, - mplDeprecation) + addendum = ( + "In order to force the use of a specific Qt binding, " + "either import that binding first, or set the QT_API " + "environment variable.") + cbook.warn_deprecated( + "2.2", key, obj_type="rcparam", addendum=addendum) elif key in _deprecated_ignore_map: - alt = _deprecated_ignore_map[key] - warnings.warn(self.msg_depr_ignore % (key, alt), - mplDeprecation) - return - elif key in _obsolete_set: - warnings.warn(self.msg_obsolete % (key, ), - mplDeprecation) + version, alt_key = _deprecated_ignore_map[key] + cbook.warn_deprecated( + version, key, obj_type="rcparam", alternative=alt_key) return try: cval = self.validate[key](val) @@ -881,42 +905,30 @@ def __setitem__(self, key, val): 'list of valid parameters.' % (key,)) def __getitem__(self, key): - inverse_alt = None if key in _deprecated_map: - alt_key, alt_val, inverse_alt = _deprecated_map[key] - warnings.warn(self.msg_depr % (key, alt_key), - mplDeprecation) - key = alt_key + version, alt_key, alt_val, inverse_alt = _deprecated_map[key] + cbook.warn_deprecated( + version, key, obj_type="rcparam", alternative=alt_key) + return inverse_alt(dict.__getitem__(self, alt_key)) elif key in _deprecated_ignore_map: - alt = _deprecated_ignore_map[key] - warnings.warn(self.msg_depr_ignore % (key, alt), - mplDeprecation) - key = alt - - elif key in _obsolete_set: - warnings.warn(self.msg_obsolete % (key, ), - mplDeprecation) - return None - - val = dict.__getitem__(self, key) - if inverse_alt is not None: - return inverse_alt(val) - else: - return val + version, alt_key = _deprecated_ignore_map[key] + cbook.warn_deprecated( + version, key, obj_type, alternative=alt_key) + return dict.__getitem__(self, alt_key) if alt_key else None + + return dict.__getitem__(self, key) def __repr__(self): - import pprint class_name = self.__class__.__name__ indent = len(class_name) + 1 repr_split = pprint.pformat(dict(self), indent=1, width=80 - indent).split('\n') repr_indented = ('\n' + ' ' * indent).join(repr_split) - return '{0}({1})'.format(class_name, repr_indented) + return '{}({})'.format(class_name, repr_indented) def __str__(self): - return '\n'.join('{0}: {1}'.format(k, v) - for k, v in sorted(self.items())) + return '\n'.join(map('{0[0]}: {0[1]}'.format, sorted(self.items()))) def __iter__(self): """Yield sorted list of keys.""" @@ -1043,10 +1055,10 @@ def _rc_params_in_file(fname, fail_on_error=False): warnings.warn('Bad val "%s" on %s\n\t%s' % (val, error_details, msg)) elif key in _deprecated_ignore_map: - warnings.warn('%s is deprecated. Update your matplotlibrc to use ' - '%s instead.' % (key, _deprecated_ignore_map[key]), - mplDeprecation) - + version, alt_key = _deprecated_ignore_map[key] + cbook.warn_deprecated( + version, key, alternative=alt_key, + addendum="Please update your matplotlibrc.") else: print(""" Bad key "%s" on line %d in diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index 181293b7983c..60d2cea20ad8 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -1310,8 +1310,8 @@ def set_adjustable(self, adjustable, share=False): and independently on each Axes as it is drawn. """ if adjustable == 'box-forced': - warnings.warn("The 'box-forced' keyword argument is deprecated" - " since 2.2.", cbook.mplDeprecation, stacklevel=2) + cbook.warn_deprecated( + "2.2", "box-forced", obj_type="keyword argument") if adjustable not in ('box', 'datalim', 'box-forced'): raise ValueError("argument must be 'box', or 'datalim'") if share: diff --git a/lib/matplotlib/axes/_subplots.py b/lib/matplotlib/axes/_subplots.py index accdeb456f1b..725fcb59b12f 100644 --- a/lib/matplotlib/axes/_subplots.py +++ b/lib/matplotlib/axes/_subplots.py @@ -4,7 +4,6 @@ from matplotlib import docstring import matplotlib.artist as martist from matplotlib.axes._axes import Axes -from matplotlib.cbook import mplDeprecation from matplotlib.gridspec import GridSpec, SubplotSpec import matplotlib._layoutbox as layoutbox diff --git a/lib/matplotlib/cbook/deprecation.py b/lib/matplotlib/cbook/deprecation.py index ae7f51d598c6..6ba7ba589ec3 100644 --- a/lib/matplotlib/cbook/deprecation.py +++ b/lib/matplotlib/cbook/deprecation.py @@ -42,7 +42,8 @@ def _generate_deprecation_message( if removal else ""))) + "." - + (" Use %(alternative)s instead." if alternative else "")) + + (" Use %(alternative)s instead." if alternative else "") + + (" %(addendum)s" if addendum else "")) return ( message % dict(func=name, name=name, obj_type=obj_type, since=since, @@ -103,9 +104,9 @@ def warn_deprecated( obj_type='module') """ - message = _generate_deprecation_message( - since, message, name, alternative, pending, obj_type, removal=removal) - message = '\n' + message + message = '\n' + _generate_deprecation_message( + since, message, name, alternative, pending, obj_type, addendum, + removal=removal) category = (PendingDeprecationWarning if pending else MatplotlibDeprecationWarning) warnings.warn(message, category, stacklevel=2) diff --git a/lib/matplotlib/gridspec.py b/lib/matplotlib/gridspec.py index efcfb1e879c8..baaab83a217e 100644 --- a/lib/matplotlib/gridspec.py +++ b/lib/matplotlib/gridspec.py @@ -23,7 +23,6 @@ from matplotlib import _pylab_helpers, tight_layout, rcParams from matplotlib.transforms import Bbox import matplotlib._layoutbox as layoutbox -from matplotlib.cbook import mplDeprecation _log = logging.getLogger(__name__) @@ -277,8 +276,8 @@ def get_subplot_params(self, figure=None, fig=None): parameters are from rcParams unless a figure attribute is set. """ if fig is not None: - warnings.warn("the 'fig' kwarg is deprecated " - "use 'figure' instead", mplDeprecation) + cbook.warn_deprecated("2.2", "fig", obj_type="keyword argument", + alternative="figure") if figure is None: figure = fig @@ -367,8 +366,8 @@ def get_subplot_params(self, figure=None, fig=None): """Return a dictionary of subplot layout parameters. """ if fig is not None: - warnings.warn("the 'fig' kwarg is deprecated " - "use 'figure' instead", mplDeprecation) + cbook.warn_deprecated("2.2", "fig", obj_type="keyword argument", + alternative="figure") if figure is None: figure = fig diff --git a/lib/matplotlib/tests/test_rcparams.py b/lib/matplotlib/tests/test_rcparams.py index d78c033b53da..8b28f0a1af1f 100644 --- a/lib/matplotlib/tests/test_rcparams.py +++ b/lib/matplotlib/tests/test_rcparams.py @@ -453,7 +453,7 @@ 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_set} + deprecated = {*mpl._all_deprecated, *mpl._deprecated_remain_as_none} path_to_rc = os.path.join(mpl.get_data_path(), 'matplotlibrc') with open(path_to_rc, "r") as f: rclines = f.readlines() @@ -472,8 +472,8 @@ def test_if_rctemplate_is_up_to_date(): if not found: missing.update({k: v}) if missing: - raise ValueError("The following params are missing " + - "in the matplotlibrc.template file: {}" + raise ValueError("The following params are missing in the " + "matplotlibrc.template file: {}" .format(missing.items()))