10
10
11
11
"""
12
12
13
+ import difflib
13
14
import functools
14
15
import itertools
15
16
import pathlib
@@ -174,12 +175,19 @@ def check_shape(shape, /, **kwargs):
174
175
)
175
176
176
177
177
- def check_getitem (mapping , / , ** kwargs ):
178
+ def check_getitem (
179
+ mapping , / , _suggest_close_matches = False , _error_cls = ValueError , ** kwargs
180
+ ):
178
181
"""
179
182
*kwargs* must consist of a single *key, value* pair. If *key* is in
180
183
*mapping*, return ``mapping[value]``; else, raise an appropriate
181
184
ValueError.
182
185
186
+ Parameters
187
+ ----------
188
+ _suggest_close_matches
189
+ If True, suggest only close matches instead of all valid values.
190
+
183
191
Examples
184
192
--------
185
193
>>> _api.check_getitem({"foo": "bar"}, arg=arg)
@@ -190,9 +198,14 @@ def check_getitem(mapping, /, **kwargs):
190
198
try :
191
199
return mapping [v ]
192
200
except KeyError :
193
- raise ValueError (
194
- f"{ v !r} is not a valid value for { k } ; supported values are "
195
- f"{ ', ' .join (map (repr , mapping ))} " ) from None
201
+ if _suggest_close_matches :
202
+ if len (best := difflib .get_close_matches (v , mapping .keys (), cutoff = 0.5 )):
203
+ suggestion = f"Did you mean one of { best } ?"
204
+ else :
205
+ suggestion = ""
206
+ else :
207
+ suggestion = f"Supported values are { ', ' .join (map (repr , mapping ))} "
208
+ raise _error_cls (f"{ v !r} is not a valid value for { k } . { suggestion } " ) from None
196
209
197
210
198
211
def caching_module_getattr (cls ):
0 commit comments