Skip to content

Commit 43bdfce

Browse files
committed
Include close matches when key not found
1 parent abda9dd commit 43bdfce

File tree

4 files changed

+55
-8
lines changed

4 files changed

+55
-8
lines changed

lib/matplotlib/__init__.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -740,12 +740,16 @@ def __setitem__(self, key, val):
740740
and val is rcsetup._auto_backend_sentinel
741741
and "backend" in self):
742742
return
743+
744+
_api.check_in_keys(
745+
key,
746+
self.validate,
747+
error_string=("{value} is not a valid rc parameter. "
748+
"See rcParams.keys() for a list of valid parameters. "
749+
"{matches_str}")
750+
)
743751
try:
744752
cval = self.validate[key](val)
745-
except KeyError as err:
746-
raise KeyError(
747-
f"{key} is not a valid rc parameter (see rcParams.keys() for "
748-
f"a list of valid parameters)") from err
749753
except ValueError as ve:
750754
raise ValueError(f"Key {key}: {ve}") from None
751755
self._set(key, cval)

lib/matplotlib/_api/__init__.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
1111
"""
1212

13+
import difflib
1314
import functools
1415
import itertools
1516
import pathlib
@@ -139,6 +140,35 @@ def check_in_list(values, /, *, _print_supported_values=True, **kwargs):
139140
raise ValueError(msg)
140141

141142

143+
def check_in_keys(value, mappable, *,
144+
error_string="{value!r} not found. {matches_str}"):
145+
"""
146+
Check if *value* is in the keys of *mappable*.
147+
148+
Parameters
149+
----------
150+
value :
151+
Value to check for in keys of *mappable*.
152+
mappable :
153+
A mappable object with keys.
154+
error_string:
155+
String to use to format error.
156+
Must contain fields for *value* and *matches_str*.
157+
158+
Raises
159+
------
160+
KeyError
161+
If *value* is not in the keys of *mappable*.
162+
"""
163+
valid = list(mappable)
164+
if value not in valid:
165+
matches_str = ""
166+
if len(best := difflib.get_close_matches(value, valid, cutoff=.1)):
167+
matches_str = f"Did you mean one of {best}?"
168+
raise KeyError(error_string.format(value=value, matches_str=matches_str))
169+
170+
171+
142172
def check_shape(shape, /, **kwargs):
143173
"""
144174
For each *key, value* pair in *kwargs*, check that *value* has the shape *shape*;

lib/matplotlib/cm.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,10 +92,12 @@ def __init__(self, cmaps):
9292
self._builtin_cmaps = tuple(cmaps)
9393

9494
def __getitem__(self, item):
95-
try:
96-
return self._cmaps[item].copy()
97-
except KeyError:
98-
raise KeyError(f"{item!r} is not a known colormap name") from None
95+
_api.check_in_keys(
96+
item,
97+
self._cmaps,
98+
error_string="{value!r} is not a known colormap name. {matches_str}"
99+
)
100+
return self._cmaps[item].copy()
99101

100102
def __iter__(self):
101103
return iter(self._cmaps)

lib/matplotlib/tests/test_colors.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1828,3 +1828,14 @@ def test_LinearSegmentedColormap_from_list_value_color_tuple():
18281828
cmap([value for value, _ in value_color_tuples]),
18291829
to_rgba_array([color for _, color in value_color_tuples]),
18301830
)
1831+
1832+
1833+
def test_close_error_name():
1834+
with pytest.raises(KeyError) as exinfo:
1835+
matplotlib.colormaps["grays"]
1836+
1837+
msg = exinfo.value.args[0]
1838+
assert msg == (
1839+
"'grays' is not a known colormap name. "
1840+
"Did you mean one of ['gray', 'Grays', 'gray_r']?"
1841+
)

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy