14
14
"""
15
15
16
16
import ast
17
- from functools import partial , reduce
17
+ from functools import lru_cache , reduce
18
18
import logging
19
19
from numbers import Number
20
20
import operator
@@ -81,18 +81,19 @@ def __call__(self, s):
81
81
raise ValueError (msg )
82
82
83
83
84
- def _listify_validator (scalar_validator , allow_stringlist = False , * , doc = None ):
84
+ @lru_cache ()
85
+ def _listify_validator (scalar_validator , allow_stringlist = False , * ,
86
+ n = None , doc = None ):
85
87
def f (s ):
86
88
if isinstance (s , str ):
87
89
try :
88
- return [scalar_validator (v .strip ()) for v in s .split (',' )
89
- if v .strip ()]
90
+ val = [scalar_validator (v .strip ()) for v in s .split (',' )
91
+ if v .strip ()]
90
92
except Exception :
91
93
if allow_stringlist :
92
94
# Sometimes, a list of colors might be a single string
93
95
# of single-letter colornames. So give that a shot.
94
- return [scalar_validator (v .strip ())
95
- for v in s if v .strip ()]
96
+ val = [scalar_validator (v .strip ()) for v in s if v .strip ()]
96
97
else :
97
98
raise
98
99
# Allow any ordered sequence type -- generators, np.ndarray, pd.Series
@@ -102,11 +103,16 @@ def f(s):
102
103
# behavior of filtering out any empty strings (behavior was
103
104
# from the original validate_stringlist()), while allowing
104
105
# any non-string/text scalar values such as numbers and arrays.
105
- return [scalar_validator (v ) for v in s
106
- if not isinstance (v , str ) or v ]
106
+ val = [scalar_validator (v ) for v in s
107
+ if not isinstance (v , str ) or v ]
107
108
else :
108
- raise ValueError ("{!r} must be of type: str or non-dictionary "
109
- "iterable" .format (s ))
109
+ raise ValueError (
110
+ f"Expected str or other non-set iterable, but got { s } " )
111
+ if n is not None and len (val ) != n :
112
+ raise ValueError (
113
+ f"Expected { n } values, but there are { len (val )} values in { s } " )
114
+ return val
115
+
110
116
try :
111
117
f .__name__ = "{}list" .format (scalar_validator .__name__ )
112
118
except AttributeError : # class instance.
@@ -295,6 +301,7 @@ def validate_backend(s):
295
301
_deprecated_since = "3.3" )
296
302
297
303
304
+ @cbook .deprecated ("3.3" )
298
305
def _make_nseq_validator (cls , n = None , allow_none = False ):
299
306
300
307
def validator (s ):
@@ -320,8 +327,14 @@ def validator(s):
320
327
return validator
321
328
322
329
323
- validate_nseq_float = partial (_make_nseq_validator , float )
324
- validate_nseq_int = partial (_make_nseq_validator , int )
330
+ @cbook .deprecated ("3.3" )
331
+ def validate_nseq_float (n ):
332
+ return _make_nseq_validator (float , n )
333
+
334
+
335
+ @cbook .deprecated ("3.3" )
336
+ def validate_nseq_int (n ):
337
+ return _make_nseq_validator (int , n )
325
338
326
339
327
340
def validate_color_or_inherit (s ):
@@ -480,12 +493,10 @@ def validate_whiskers(s):
480
493
return 'range'
481
494
else :
482
495
try :
483
- v = validate_nseq_float (2 )(s )
484
- return v
496
+ return _listify_validator (validate_float , n = 2 )(s )
485
497
except (TypeError , ValueError ):
486
498
try :
487
- v = float (s )
488
- return v
499
+ return float (s )
489
500
except ValueError as e :
490
501
raise ValueError ("Not a valid whisker value ['range', float, "
491
502
"(float, float)]" ) from e
@@ -746,7 +757,7 @@ def validate_sketch(s):
746
757
if s == 'none' or s is None :
747
758
return None
748
759
try :
749
- return tuple (validate_nseq_float ( 3 )(s ))
760
+ return tuple (_listify_validator ( validate_float , n = 3 )(s ))
750
761
except ValueError :
751
762
raise ValueError ("Expected a (scale, length, randomness) triplet" )
752
763
@@ -1226,7 +1237,7 @@ def _convert_validator_spec(key, conv):
1226
1237
"axes.labelcolor" : validate_color , # color of axis label
1227
1238
# use scientific notation if log10 of the axis range is smaller than the
1228
1239
# first or larger than the second
1229
- "axes.formatter.limits" : validate_nseq_int ( 2 ),
1240
+ "axes.formatter.limits" : _listify_validator ( validate_int , n = 2 ),
1230
1241
# use current locale to format ticks
1231
1242
"axes.formatter.use_locale" : validate_bool ,
1232
1243
"axes.formatter.use_mathtext" : validate_bool ,
@@ -1351,7 +1362,7 @@ def _convert_validator_spec(key, conv):
1351
1362
"figure.titleweight" : validate_fontweight ,
1352
1363
1353
1364
# figure size in inches: width by height
1354
- "figure.figsize" : validate_nseq_float ( 2 ),
1365
+ "figure.figsize" : _listify_validator ( validate_float , n = 2 ),
1355
1366
"figure.dpi" : validate_float ,
1356
1367
"figure.facecolor" : validate_color ,
1357
1368
"figure.edgecolor" : validate_color ,
0 commit comments