Skip to content

Commit bc4b029

Browse files
tacaswellgreglucas
andcommitted
API: Add pending deprecation to mpl.cm top level functions
- matplotlib.cm.get_cmap - matplotlib.cm.register_cmap - matplotlib.cm.unregister_cmap - matplotlib.pyplot.register_cmap in preference for working with the ColormapRegistry on the top level module. Co-authored-by: Greg Lucas <greg.m.lucas@gmail.com>
1 parent bf6bb85 commit bc4b029

File tree

4 files changed

+93
-18
lines changed

4 files changed

+93
-18
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
Pending deprecation top-level cmap registration and access functions in ``mpl.cm``
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
4+
As part of a `multi-step process
5+
<https://github.com/matplotlib/matplotlib/issues/20853>`_ we are refactoring
6+
the global state for managing the registered colormaps.
7+
8+
In Matplotlib 3.5 we added a `.ColormapRegistry` class and exposed an
9+
instance at the top level as ``matplotlib.colormaps``. The existing
10+
top level functions in `matplotlib.cm` (``get_cmap``, ``register_cmap``,
11+
``unregister_cmap``) were changed to be aliases around the same instance.
12+
13+
In Matplotlib 3.6 we have marked those top level functions as pending
14+
deprecation with the intention of deprecation in Matplotlib 3.7. The
15+
following functions have been marked for pending deprecation:
16+
17+
- `matplotlib.cm.get_cmap`
18+
- `matplotlib.cm.register_cmap`
19+
- `matplotlib.cm.unregister_cmap`
20+
- ``matplotlib.pyplot.register_cmap``
21+
22+
The ``matplotlib.pyplot.get_cmap`` function is intentionally exempted from this
23+
deprecation process.

lib/matplotlib/cm.py

+21-1
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,11 @@ def unregister(self, name):
201201
globals().update(_colormaps)
202202

203203

204+
@_api.deprecated(
205+
'3.6',
206+
pending=True,
207+
alternative="``matplotlib.colormaps.register_cmap(name)``"
208+
)
204209
def register_cmap(name=None, cmap=None, *, override_builtin=False):
205210
"""
206211
Add a colormap to the set recognized by :func:`get_cmap`.
@@ -244,7 +249,7 @@ def register_cmap(name=None, cmap=None, *, override_builtin=False):
244249
_colormaps._allow_override_builtin = False
245250

246251

247-
def get_cmap(name=None, lut=None):
252+
def _get_cmap(name=None, lut=None):
248253
"""
249254
Get a colormap instance, defaulting to rc values if *name* is None.
250255
@@ -260,6 +265,10 @@ def get_cmap(name=None, lut=None):
260265
lut : int or None, default: None
261266
If *name* is not already a Colormap instance and *lut* is not None, the
262267
colormap will be resampled to have *lut* entries in the lookup table.
268+
269+
Returns
270+
-------
271+
Colormap
263272
"""
264273
if name is None:
265274
name = mpl.rcParams['image.cmap']
@@ -271,7 +280,18 @@ def get_cmap(name=None, lut=None):
271280
else:
272281
return _colormaps[name].resampled(lut)
273282

283+
# do it in two steps like this so we can have an un-deprecated version in
284+
# pyplot.
285+
get_cmap = _api.deprecated(
286+
'3.6', pending=True, alternative="``matplotlib.colormaps[name]``"
287+
)(_get_cmap)
288+
274289

290+
@_api.deprecated(
291+
'3.6',
292+
pending=True,
293+
alternative="``matplotlib.colormaps.unregister_cmap(name)``"
294+
)
275295
def unregister_cmap(name):
276296
"""
277297
Remove a colormap recognized by :func:`get_cmap`.

lib/matplotlib/pyplot.py

+8-3
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@
6868
from matplotlib.scale import get_scale_names
6969

7070
from matplotlib import cm
71-
from matplotlib.cm import _colormaps as colormaps, get_cmap, register_cmap
71+
from matplotlib.cm import _colormaps as colormaps, register_cmap
7272
from matplotlib.colors import _color_sequences as color_sequences
7373

7474
import numpy as np
@@ -2022,7 +2022,7 @@ def get_plot_commands():
20222022
# This works by searching for all functions in this module and removing
20232023
# a few hard-coded exclusions, as well as all of the colormap-setting
20242024
# functions, and anything marked as private with a preceding underscore.
2025-
exclude = {'colormaps', 'colors', 'get_plot_commands',
2025+
exclude = {'colormaps', 'colors', 'get_plot_commands', 'get_cmap',
20262026
*_NON_PLOT_COMMANDS, *colormaps}
20272027
this_module = inspect.getmodule(get_plot_commands)
20282028
return sorted(
@@ -2069,6 +2069,11 @@ def clim(vmin=None, vmax=None):
20692069
im.set_clim(vmin, vmax)
20702070

20712071

2072+
def get_cmap(name=None, lut=None):
2073+
return cm._get_cmap(name=name, lut=lut)
2074+
get_cmap.__doc__ = cm._get_cmap.__doc__
2075+
2076+
20722077
def set_cmap(cmap):
20732078
"""
20742079
Set the default colormap, and applies it to the current image if any.
@@ -2084,7 +2089,7 @@ def set_cmap(cmap):
20842089
matplotlib.cm.register_cmap
20852090
matplotlib.cm.get_cmap
20862091
"""
2087-
cmap = colormaps[cmap]
2092+
cmap = get_cmap(cmap)
20882093

20892094
rc('image', cmap=cmap.name)
20902095
im = gci()

lib/matplotlib/tests/test_colors.py

+41-14
Original file line numberDiff line numberDiff line change
@@ -65,44 +65,71 @@ def test_resampled():
6565

6666

6767
def test_register_cmap():
68-
new_cm = cm.get_cmap("viridis")
68+
new_cm = mpl.colormaps["viridis"]
6969
target = "viridis2"
70-
cm.register_cmap(target, new_cm)
71-
assert plt.get_cmap(target) == new_cm
70+
with pytest.warns(
71+
PendingDeprecationWarning,
72+
match=r"matplotlib\.colormaps\.register_cmap\(name\)"
73+
):
74+
cm.register_cmap(target, new_cm)
75+
assert mpl.colormaps[target] == new_cm
7276

7377
with pytest.raises(ValueError,
7478
match="Arguments must include a name or a Colormap"):
75-
cm.register_cmap()
76-
77-
cm.unregister_cmap(target)
79+
with pytest.warns(
80+
PendingDeprecationWarning,
81+
match=r"matplotlib\.colormaps\.register_cmap\(name\)"
82+
):
83+
cm.register_cmap()
84+
85+
with pytest.warns(
86+
PendingDeprecationWarning,
87+
match=r"matplotlib\.colormaps\.unregister_cmap\(name\)"
88+
):
89+
cm.unregister_cmap(target)
7890
with pytest.raises(ValueError,
7991
match=f'{target!r} is not a valid value for name;'):
80-
cm.get_cmap(target)
81-
# test that second time is error free
82-
cm.unregister_cmap(target)
92+
with pytest.warns(
93+
PendingDeprecationWarning,
94+
match=r"matplotlib\.colormaps\[name\]"
95+
):
96+
cm.get_cmap(target)
97+
with pytest.warns(
98+
PendingDeprecationWarning,
99+
match=r"matplotlib\.colormaps\.unregister_cmap\(name\)"
100+
):
101+
# test that second time is error free
102+
cm.unregister_cmap(target)
83103

84104
with pytest.raises(TypeError, match="'cmap' must be"):
85-
cm.register_cmap('nome', cmap='not a cmap')
105+
with pytest.warns(
106+
PendingDeprecationWarning,
107+
match=r"matplotlib\.colormaps\.register_cmap\(name\)"
108+
):
109+
cm.register_cmap('nome', cmap='not a cmap')
86110

87111

88112
def test_double_register_builtin_cmap():
89113
name = "viridis"
90114
match = f"Re-registering the builtin cmap {name!r}."
91115
with pytest.raises(ValueError, match=match):
92116
matplotlib.colormaps.register(
93-
cm.get_cmap(name), name=name, force=True
117+
mpl.colormaps[name], name=name, force=True
94118
)
95119
with pytest.raises(ValueError, match='A colormap named "viridis"'):
96-
cm.register_cmap(name, cm.get_cmap(name))
120+
with pytest.warns():
121+
cm.register_cmap(name, mpl.colormaps[name])
97122
with pytest.warns(UserWarning):
98-
cm.register_cmap(name, cm.get_cmap(name), override_builtin=True)
123+
# TODO is warning more than once!
124+
cm.register_cmap(name, mpl.colormaps[name], override_builtin=True)
99125

100126

101127
def test_unregister_builtin_cmap():
102128
name = "viridis"
103129
match = f'cannot unregister {name!r} which is a builtin colormap.'
104130
with pytest.raises(ValueError, match=match):
105-
cm.unregister_cmap(name)
131+
with pytest.warns():
132+
cm.unregister_cmap(name)
106133

107134

108135
def test_colormap_copy():

0 commit comments

Comments
 (0)