Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 17bb516

Browse files
committed
Deprecation warning for cmap_d.
1 parent 67ffc66 commit 17bb516

File tree

7 files changed

+86
-26
lines changed

7 files changed

+86
-26
lines changed

examples/images_contours_and_fields/demo_bboximage.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
a = np.vstack((a, a))
3939

4040
# List of all colormaps; skip reversed colormaps.
41-
maps = sorted(m for m in plt.cm.cmap_d if not m.endswith("_r"))
41+
maps = sorted(m for m in plt.colormaps() if not m.endswith("_r"))
4242

4343
ncol = 2
4444
nrow = len(maps)//ncol + 1

lib/matplotlib/backends/qt_editor/figureoptions.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,11 +139,11 @@ def prepare_data(d, init):
139139
mappabledict[label] = mappable
140140
mappablelabels = sorted(mappabledict, key=cmp_key)
141141
mappables = []
142-
cmaps = [(cmap, name) for name, cmap in sorted(cm.cmap_d.items())]
142+
cmaps = [(cmap, name) for name, cmap in sorted(cm._cmap_registry.items())]
143143
for label in mappablelabels:
144144
mappable = mappabledict[label]
145145
cmap = mappable.get_cmap()
146-
if cmap not in cm.cmap_d.values():
146+
if cmap not in cm._cmap_registry.values():
147147
cmaps = [(cmap, cmap.name), *cmaps]
148148
low, high = mappable.get_clim()
149149
mappabledata = [

lib/matplotlib/cm.py

Lines changed: 64 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
normalization.
1616
"""
1717

18+
from collections.abc import MutableMapping
1819
import functools
1920

2021
import numpy as np
@@ -49,7 +50,7 @@ def revcmap(data):
4950
LUTSIZE = mpl.rcParams['image.lut']
5051

5152

52-
def _gen_cmap_d():
53+
def _gen_cmap_registry():
5354
"""
5455
Generate a dict mapping standard colormap names to standard colormaps, as
5556
well as the reversed colormaps.
@@ -71,10 +72,48 @@ def _gen_cmap_d():
7172
return cmap_d
7273

7374

74-
_cmap_d = _gen_cmap_d()
75-
locals().update(_cmap_d)
75+
class _DeprecatedCmapDict(MutableMapping):
76+
"""Dictionary mapping for deprecated _cmap_d access."""
77+
78+
def __init__(self, cmap_registry):
79+
self._cmap_registry = cmap_registry
80+
81+
def __delitem__(self, key):
82+
self._warn_deprecated()
83+
self._cmap_registry.__delitem__(key)
84+
85+
def __getitem__(self, key):
86+
self._warn_deprecated()
87+
return self._cmap_registry.__getitem__(key)
88+
89+
def __iter__(self):
90+
return self._cmap_registry.__iter__()
91+
92+
def __len__(self):
93+
return self._cmap_registry.__len__()
94+
95+
def __setitem__(self, key, val):
96+
self._warn_deprecated()
97+
self._cmap_registry.__setitem__(key, val)
98+
99+
def get(self, key, default=None):
100+
self._warn_deprecated()
101+
return self._cmap_registry.get(key, default)
102+
103+
def _warn_deprecated(self):
104+
cbook.warn_deprecated(
105+
"3.3",
106+
message="The global colormaps dictionary is no longer "
107+
"considered public API.",
108+
alternative="Please use register_cmap() and get_cmap() to "
109+
"access the contents of the dictionary."
110+
)
111+
112+
113+
_cmap_registry = _gen_cmap_registry()
114+
locals().update(_cmap_registry)
76115
# This is no longer considered public API
77-
cmap_d = _cmap_d
116+
cmap_d = _DeprecatedCmapDict(_cmap_registry)
78117

79118

80119
# Continue with definitions ...
@@ -99,6 +138,13 @@ def register_cmap(name=None, cmap=None, data=None, lut=None):
99138
and the resulting colormap is registered. Instead of this implicit
100139
colormap creation, create a `.LinearSegmentedColormap` and use the first
101140
case: ``register_cmap(cmap=LinearSegmentedColormap(name, data, lut))``.
141+
142+
Notes
143+
-----
144+
Registering a colormap stores a reference to the colormap object
145+
which can currently be modified and inadvertantly change the global
146+
colormap state. This behavior is deprecated and in Matplotlib 3.5
147+
the registered colormap will be immutable.
102148
"""
103149
cbook._check_isinstance((str, None), name=name)
104150
if name is None:
@@ -109,7 +155,7 @@ def register_cmap(name=None, cmap=None, data=None, lut=None):
109155
"Colormap") from err
110156
if isinstance(cmap, colors.Colormap):
111157
cmap._global = True
112-
_cmap_d[name] = cmap
158+
_cmap_registry[name] = cmap
113159
return
114160
if lut is not None or data is not None:
115161
cbook.warn_deprecated(
@@ -123,7 +169,7 @@ def register_cmap(name=None, cmap=None, data=None, lut=None):
123169
lut = mpl.rcParams['image.lut']
124170
cmap = colors.LinearSegmentedColormap(name, data, lut)
125171
cmap._global = True
126-
_cmap_d[name] = cmap
172+
_cmap_registry[name] = cmap
127173

128174

129175
def get_cmap(name=None, lut=None):
@@ -133,15 +179,18 @@ def get_cmap(name=None, lut=None):
133179
Colormaps added with :func:`register_cmap` take precedence over
134180
built-in colormaps.
135181
182+
Notes
183+
-----
184+
Currently, this returns the global colormap object, which is deprecated.
185+
In Matplotlib 3.5, you will no longer be able to modify the global
186+
colormaps in-place.
187+
136188
Parameters
137189
----------
138190
name : `matplotlib.colors.Colormap` or str or None, default: None
139-
If a `.Colormap` instance, it will be returned.
140-
Otherwise, the name of a colormap known to Matplotlib, which will
141-
be resampled by *lut*. Currently, this returns the global colormap
142-
object, which is deprecated. In Matplotlib 3.5, you will no longer be
143-
able to modify the global colormaps in-place.
144-
The default, None, means :rc:`image.cmap`.
191+
If a `.Colormap` instance, it will be returned. Otherwise, the name of
192+
a colormap known to Matplotlib, which will be resampled by *lut*. The
193+
default, None, means :rc:`image.cmap`.
145194
lut : int or None, default: None
146195
If *name* is not already a Colormap instance and *lut* is not None, the
147196
colormap will be resampled to have *lut* entries in the lookup table.
@@ -150,11 +199,11 @@ def get_cmap(name=None, lut=None):
150199
name = mpl.rcParams['image.cmap']
151200
if isinstance(name, colors.Colormap):
152201
return name
153-
cbook._check_in_list(sorted(_cmap_d), name=name)
202+
cbook._check_in_list(sorted(_cmap_registry), name=name)
154203
if lut is None:
155-
return _cmap_d[name]
204+
return _cmap_registry[name]
156205
else:
157-
return _cmap_d[name]._resample(lut)
206+
return _cmap_registry[name]._resample(lut)
158207

159208

160209
class ScalarMappable:

lib/matplotlib/colors.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -484,8 +484,8 @@ def makeMappingArray(N, data, gamma=1.0):
484484
return _create_lookup_table(N, data, gamma)
485485

486486

487-
def _deprecate_global_cmap(cmap):
488-
if hasattr(cmap, '_global') and cmap._global:
487+
def _warn_if_global_cmap_modified(cmap):
488+
if getattr(cmap, '_global', False):
489489
cbook.warn_deprecated(
490490
"3.3",
491491
message="You are modifying the state of a globally registered "
@@ -619,28 +619,28 @@ def __copy__(self):
619619

620620
def set_bad(self, color='k', alpha=None):
621621
"""Set the color for masked values."""
622+
_warn_if_global_cmap_modified(self)
622623
self._rgba_bad = to_rgba(color, alpha)
623624
if self._isinit:
624625
self._set_extremes()
625-
_deprecate_global_cmap(self)
626626

627627
def set_under(self, color='k', alpha=None):
628628
"""
629629
Set the color for low out-of-range values when ``norm.clip = False``.
630630
"""
631+
_warn_if_global_cmap_modified(self)
631632
self._rgba_under = to_rgba(color, alpha)
632633
if self._isinit:
633634
self._set_extremes()
634-
_deprecate_global_cmap(self)
635635

636636
def set_over(self, color='k', alpha=None):
637637
"""
638638
Set the color for high out-of-range values when ``norm.clip = False``.
639639
"""
640+
_warn_if_global_cmap_modified(self)
640641
self._rgba_over = to_rgba(color, alpha)
641642
if self._isinit:
642643
self._set_extremes()
643-
_deprecate_global_cmap(self)
644644

645645
def _set_extremes(self):
646646
if self._rgba_under:

lib/matplotlib/pyplot.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1969,7 +1969,7 @@ def colormaps():
19691969
<https://www.mathworks.com/matlabcentral/fileexchange/2662-cmrmap-m>`_
19701970
by Carey Rappaport
19711971
"""
1972-
return sorted(cm.cmap_d)
1972+
return sorted(cm._cmap_registry)
19731973

19741974

19751975
def _setup_pyplot_info_docstrings():

lib/matplotlib/tests/test_colors.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,17 @@ def test_colormap_global_set_warn():
126126
plt.register_cmap(cmap=orig_cmap)
127127

128128

129+
def test_colormap_dict_deprecate():
130+
# Make sure we warn on get and set access into cmap_d
131+
with pytest.warns(cbook.MatplotlibDeprecationWarning,
132+
match="The global colormaps dictionary is no longer"):
133+
cm = plt.cm.cmap_d['viridis']
134+
135+
with pytest.warns(cbook.MatplotlibDeprecationWarning,
136+
match="The global colormaps dictionary is no longer"):
137+
plt.cm.cmap_d['test'] = cm
138+
139+
129140
def test_colormap_copy():
130141
cm = plt.cm.Reds
131142
cm_copy = copy.copy(cm)
@@ -874,7 +885,7 @@ def test_pandas_iterable(pd):
874885
assert_array_equal(cm1.colors, cm2.colors)
875886

876887

877-
@pytest.mark.parametrize('name', sorted(cm.cmap_d))
888+
@pytest.mark.parametrize('name', sorted(plt.colormaps()))
878889
def test_colormap_reversing(name):
879890
"""
880891
Check the generated _lut data of a colormap and corresponding reversed

lib/matplotlib/tests/test_pickle.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ def test_shared():
190190
assert fig.axes[1].get_xlim() == (10, 20)
191191

192192

193-
@pytest.mark.parametrize("cmap", cm.cmap_d.values())
193+
@pytest.mark.parametrize("cmap", cm._cmap_registry.values())
194194
def test_cmap(cmap):
195195
pickle.dumps(cmap)
196196

0 commit comments

Comments
 (0)