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

Skip to content

Commit d5a8b91

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

File tree

4 files changed

+79
-19
lines changed

4 files changed

+79
-19
lines changed

lib/matplotlib/cm.py

Lines changed: 62 additions & 13 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
139191
If a `.Colormap` instance, it will be returned.
140192
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`.
193+
be resampled by *lut*. The 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/tests/test_colors.py

Lines changed: 11 additions & 0 deletions
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)

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)