Skip to content

Commit 04538ba

Browse files
committed
Make ColorDatabase MutableMapping and expand 'grey' translations
1 parent 7da4c44 commit 04538ba

2 files changed

Lines changed: 40 additions & 27 deletions

File tree

proplot/colors.py

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2795,14 +2795,14 @@ def _get_rgba(self, arg, alpha):
27952795
"""
27962796
key = (arg, alpha)
27972797
if isinstance(arg, str) or not np.iterable(arg) or len(arg) != 2:
2798-
return super().__getitem__(key)
2798+
return dict.__getitem__(self, key)
27992799
if not isinstance(arg[0], str) or not isinstance(arg[1], Number):
2800-
return super().__getitem__(key)
2800+
return dict.__getitem__(self, key)
28012801
# Try to get the colormap
28022802
try:
28032803
cmap = _cmap_database[arg[0]]
28042804
except (KeyError, TypeError):
2805-
return super().__getitem__(key)
2805+
return dict.__getitem__(self, key)
28062806
# Read the colormap value
28072807
if isinstance(cmap, DiscreteColormap):
28082808
if not 0 <= arg[1] < len(cmap.colors):
@@ -2824,22 +2824,36 @@ def _get_rgba(self, arg, alpha):
28242824
return (*rgba[:3], a)
28252825

28262826

2827-
class ColorDatabase(dict):
2827+
class ColorDatabase(MutableMapping, dict):
28282828
"""
28292829
Dictionary subclass used to replace the builtin matplotlib color database.
28302830
See `~ColorDatabase.__getitem__` for details.
28312831
"""
2832-
# NOTE: Matplotlib's database also inherits from dict. MutableMapping not needed
2833-
# since usage is entirely internal (we just make it public for documentation)
2834-
def __init__(self, mapping):
2832+
_regex_grey = re.compile('grey') # permit e.g. 'slategrey' and 'greyish'
2833+
2834+
def __iter__(self):
2835+
yield from dict.__iter__(self)
2836+
2837+
def __len__(self):
2838+
return dict.__len__(self)
2839+
2840+
def __delitem__(self, key):
2841+
key = self._parse_key(key)
2842+
dict.__delitem__(self, key)
2843+
self.cache.clear()
2844+
2845+
def __init__(self, mapping=None):
28352846
"""
28362847
Parameters
28372848
----------
2838-
mapping : dict-like
2849+
mapping : dict-like, optional
28392850
The colors.
28402851
"""
2841-
super().__init__(mapping)
2852+
# NOTE: Tested with and without standardization and speedup is marginal
28422853
self._cache = _ColorCache()
2854+
mapping = mapping or {}
2855+
for key, value in mapping.items():
2856+
self.__setitem__(key, value)
28432857

28442858
def __getitem__(self, key):
28452859
"""
@@ -2854,25 +2868,28 @@ def __getitem__(self, key):
28542868
This works with anywhere that colors are used in matplotlib, for example
28552869
as ``'color'``, ``'edgecolor'``, or ``'facecolor'`` arguments.
28562870
"""
2857-
if isinstance(key, str):
2858-
key = re.sub(r'\bgrey[0-9]?\b', 'gray', key)
2859-
return super().__getitem__(key)
2871+
key = self._parse_key(key)
2872+
return dict.__getitem__(self, key)
28602873

28612874
def __setitem__(self, key, value):
28622875
"""
2863-
Add a color and clear the cache.
2876+
Add a color. Translates ``grey`` into ``gray`` and clears the
2877+
cache. The color must be a string.
28642878
"""
2865-
if not isinstance(key, str):
2866-
raise ValueError(f'Invalid color name {key!r}. Must be string.')
2867-
super().__setitem__(key, value)
2879+
# Always standardize assignments.
2880+
key = self._parse_key(key)
2881+
dict.__setitem__(self, key, value)
28682882
self.cache.clear()
28692883

2870-
def __delitem__(self, key):
2884+
def _parse_key(self, key):
28712885
"""
2872-
Delete a color and clear the cache.
2886+
Parse the color key. Currently this just translates grays.
28732887
"""
2874-
super().__delitem__(key)
2875-
self.cache.clear()
2888+
if not isinstance(key, str):
2889+
raise ValueError(f'Invalid color name {key!r}. Must be string.')
2890+
if isinstance(key, str):
2891+
key = self._regex_grey.sub('gray', key.lower())
2892+
return key
28762893

28772894
@property
28782895
def cache(self):

proplot/config.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -669,15 +669,11 @@ def register_colors(*args, user=None, default=False, space='hcl', margin=0.1, **
669669
register_fonts
670670
proplot.demos.show_colors
671671
"""
672-
# Default-only actions
672+
# Add in base colors and CSS4 colors so user has no surprises
673673
from . import colors as pcolors
674674
if default:
675-
# Reset native colors dictionary
676-
pcolors._color_database.clear() # clean out!
677-
pcolors._color_database.cache.clear() # clean out!
678-
679-
# Add in base colors and CSS4 colors so user has no surprises
680-
for name, src in (('base', pcolors.COLORS_BASE), ('css', mcolors.CSS4_COLORS)):
675+
pcolors._color_database.clear() # MutableMapping ensures cache also clears
676+
for src in (pcolors.COLORS_BASE, mcolors.CSS4_COLORS):
681677
pcolors._color_database.update(src)
682678

683679
# Register input colors

0 commit comments

Comments
 (0)