Skip to content

Commit 0ab7dab

Browse files
committed
Add helper function to check that an argument is in a list of strings.
1 parent 3d7922d commit 0ab7dab

23 files changed

+113
-171
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Changed exceptions
2+
``````````````````
3+
4+
- `mpl_toolkits.axes_grid1.axes_size.GetExtentHelper` now raises `ValueError`
5+
for invalid directions instead of `KeyError`.

lib/matplotlib/axes/_base.py

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1318,8 +1318,8 @@ def set_adjustable(self, adjustable, share=False):
13181318
if adjustable == 'box-forced':
13191319
cbook.warn_deprecated(
13201320
"2.2", "box-forced", obj_type="keyword argument")
1321-
if adjustable not in ('box', 'datalim', 'box-forced'):
1322-
raise ValueError("argument must be 'box', or 'datalim'")
1321+
cbook._check_enum(['box', 'datalim', 'box-forced'],
1322+
adjustable=adjustable)
13231323
if share:
13241324
axes = set(self._shared_x_axes.get_siblings(self)
13251325
+ self._shared_y_axes.get_siblings(self))
@@ -2726,9 +2726,7 @@ def grid(self, b=None, which='major', axis='both', **kwargs):
27262726
elif b is not None:
27272727
b = _string_to_bool(b)
27282728

2729-
if axis not in ['x', 'y', 'both']:
2730-
raise ValueError("The argument 'axis' must be one of 'x', 'y' or "
2731-
"'both'.")
2729+
cbook._check_enum(['x', 'y', 'both'], axis=axis)
27322730
if axis in ['x', 'both']:
27332731
self.xaxis.grid(b, which=which, **kwargs)
27342732
if axis in ['y', 'both']:
@@ -2949,8 +2947,7 @@ def tick_params(self, axis='both', **kwargs):
29492947
also be red. Gridlines will be red and translucent.
29502948
29512949
"""
2952-
if axis not in ['x', 'y', 'both']:
2953-
raise ValueError("axis must be one of 'x', 'y' or 'both'")
2950+
cbook._check_enum(['x', 'y', 'both'], axis=axis)
29542951
if axis in ['x', 'both']:
29552952
xkw = dict(kwargs)
29562953
xkw.pop('left', None)

lib/matplotlib/axes/_subplots.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import functools
22

3-
from matplotlib import docstring
3+
from matplotlib import cbook, docstring
44
import matplotlib.artist as martist
55
from matplotlib.axes._axes import Axes
66
from matplotlib.gridspec import GridSpec, SubplotSpec

lib/matplotlib/axis.py

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -195,9 +195,7 @@ def _set_labelrotation(self, labelrotation):
195195
else:
196196
mode = 'default'
197197
angle = labelrotation
198-
if mode not in ('auto', 'default'):
199-
raise ValueError("Label rotation mode must be 'default' or "
200-
"'auto', not '{}'.".format(mode))
198+
cbook._check_enum(['auto', 'default'], **{'label rotation mode': mode})
201199
self._labelrotation = (mode, angle)
202200

203201
def apply_tickdir(self, tickdir):
@@ -1278,8 +1276,7 @@ def get_ticklabels(self, minor=False, which=None):
12781276
elif which == 'both':
12791277
return self.get_majorticklabels() + self.get_minorticklabels()
12801278
else:
1281-
raise ValueError("`which` must be one of ('minor', 'major', "
1282-
"'both') not " + str(which))
1279+
cbook._check_enum(['major', 'minor', 'both'], which=which)
12831280
if minor:
12841281
return self.get_minorticklabels()
12851282
return self.get_majorticklabels()
@@ -1443,9 +1440,7 @@ def grid(self, b=None, which='major', **kwargs):
14431440
'enabled.')
14441441
b = True
14451442
which = which.lower()
1446-
if which not in ['major', 'minor', 'both']:
1447-
raise ValueError("The argument 'which' must be one of 'major', "
1448-
"'minor' or 'both'.")
1443+
cbook._check_enum(['major', 'minor', 'both'], which=which)
14491444
gridkw = {'grid_' + item[0]: item[1] for item in kwargs.items()}
14501445

14511446
if which in ['minor', 'both']:

lib/matplotlib/backends/backend_ps.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -950,12 +950,8 @@ def _print_ps(self, outfile, format, *args,
950950
(papertype, ', '.join(papersize)))
951951

952952
orientation = orientation.lower()
953-
if orientation == 'landscape':
954-
isLandscape = True
955-
elif orientation == 'portrait':
956-
isLandscape = False
957-
else:
958-
raise RuntimeError('Orientation must be "portrait" or "landscape"')
953+
cbook._check_enum(['landscape', 'portrait'], orientation=orientation)
954+
isLandscape = (orientation == 'landscape')
959955

960956
self.figure.set_dpi(72) # Override the dpi kwarg
961957

lib/matplotlib/backends/backend_webagg_core.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@
2020
import numpy as np
2121
import tornado
2222

23+
from matplotlib import backend_bases, cbook, _png
2324
from matplotlib.backends import backend_agg
2425
from matplotlib.backend_bases import _Backend
25-
from matplotlib import backend_bases, _png
2626

2727

2828
# http://www.cambiaresearch.com/articles/15/javascript-char-codes-key-codes
@@ -162,10 +162,8 @@ def set_image_mode(self, mode):
162162
Note: diff images may not contain transparency, therefore upon
163163
draw this mode may be changed if the resulting image has any
164164
transparent component.
165-
166165
"""
167-
if mode not in ['full', 'diff']:
168-
raise ValueError('image mode must be either full or diff.')
166+
cbook._check_enum(['full', 'diff'], mode=mode)
169167
if self._current_image_mode != mode:
170168
self._current_image_mode = mode
171169
self.handle_send_image_mode(None)

lib/matplotlib/cbook/__init__.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2062,6 +2062,12 @@ def _unmultiplied_rgba8888_to_premultiplied_argb32(rgba8888):
20622062

20632063

20642064
def _check_and_log_subprocess(command, logger, **kwargs):
2065+
"""
2066+
Run *command* using `subprocess.check_output`. If it succeeds, return the
2067+
output (stdout and stderr); if not, raise an exception whose text includes
2068+
the failed command and captured output. Both the command and the output
2069+
are logged at DEBUG level on *logger*.
2070+
"""
20652071
logger.debug(command)
20662072
try:
20672073
report = subprocess.check_output(
@@ -2075,3 +2081,15 @@ def _check_and_log_subprocess(command, logger, **kwargs):
20752081
.format(command, exc.output.decode('utf-8')))
20762082
logger.debug(report)
20772083
return report
2084+
2085+
2086+
def _check_enum(values, **kwargs):
2087+
"""
2088+
For each *key, value* pair in *kwargs*, check that *value* is in *values*;
2089+
if not, raise an appropriate ValueError.
2090+
"""
2091+
for k, v in kwargs.items():
2092+
if v not in values:
2093+
raise ValueError(
2094+
"{!r} is not a valid value for {}; supported values are {}"
2095+
.format(v, k, ', '.join(map(repr, values))))

lib/matplotlib/collections.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -467,8 +467,7 @@ def set_offset_position(self, offset_position):
467467
----------
468468
offset_position : {'screen', 'data'}
469469
"""
470-
if offset_position not in ('screen', 'data'):
471-
raise ValueError("offset_position must be 'screen' or 'data'")
470+
cbook._check_enum(['screen', 'data'], offset_position=offset_position)
472471
self._offset_position = offset_position
473472
self.stale = True
474473

@@ -1383,7 +1382,8 @@ def __init__(self,
13831382
coord1 in positions]
13841383
self._is_horizontal = False
13851384
else:
1386-
raise ValueError("orientation must be 'horizontal' or 'vertical'")
1385+
cbook._check_enum(
1386+
['horizontal', 'vertical'], orientation=orientation)
13871387

13881388
LineCollection.__init__(self,
13891389
segments,
@@ -1479,7 +1479,8 @@ def set_orientation(self, orientation=None):
14791479
elif orientation.lower() == 'vertical':
14801480
is_horizontal = False
14811481
else:
1482-
raise ValueError("orientation must be 'horizontal' or 'vertical'")
1482+
cbook._check_enum(
1483+
['horizontal', 'vertical'], orientation=orientation)
14831484

14841485
if is_horizontal == self.is_horizontal():
14851486
return

lib/matplotlib/contour.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -871,9 +871,7 @@ def __init__(self, ax, *args,
871871
else:
872872
self.logscale = False
873873

874-
if self.origin not in [None, 'lower', 'upper', 'image']:
875-
raise ValueError("If given, *origin* must be one of [ 'lower' |"
876-
" 'upper' | 'image']")
874+
cbook._check_enum([None, 'lower', 'upper', 'image'], origin=origin)
877875
if self.extent is not None and len(self.extent) != 4:
878876
raise ValueError("If given, *extent* must be '[ *None* |"
879877
" (x0,x1,y0,y1) ]'")

lib/matplotlib/figure.py

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1483,23 +1483,16 @@ def subplots(self, nrows=1, ncols=1, sharex=False, sharey=False,
14831483
sharex = "all" if sharex else "none"
14841484
if isinstance(sharey, bool):
14851485
sharey = "all" if sharey else "none"
1486-
share_values = ["all", "row", "col", "none"]
1487-
if sharex not in share_values:
1488-
# This check was added because it is very easy to type
1489-
# `subplots(1, 2, 1)` when `subplot(1, 2, 1)` was intended.
1490-
# In most cases, no error will ever occur, but mysterious behavior
1491-
# will result because what was intended to be the subplot index is
1492-
# instead treated as a bool for sharex.
1493-
if isinstance(sharex, Integral):
1494-
warnings.warn(
1495-
"sharex argument to subplots() was an integer. "
1496-
"Did you intend to use subplot() (without 's')?")
1497-
1498-
raise ValueError("sharex [%s] must be one of %s" %
1499-
(sharex, share_values))
1500-
if sharey not in share_values:
1501-
raise ValueError("sharey [%s] must be one of %s" %
1502-
(sharey, share_values))
1486+
# This check was added because it is very easy to type
1487+
# `subplots(1, 2, 1)` when `subplot(1, 2, 1)` was intended.
1488+
# In most cases, no error will ever occur, but mysterious behavior
1489+
# will result because what was intended to be the subplot index is
1490+
# instead treated as a bool for sharex.
1491+
if isinstance(sharex, Integral):
1492+
warnings.warn("sharex argument to subplots() was an integer. "
1493+
"Did you intend to use subplot() (without 's')?")
1494+
cbook._check_enum(["all", "row", "col", "none"],
1495+
sharex=sharex, sharey=sharey)
15031496
if subplot_kw is None:
15041497
subplot_kw = {}
15051498
if gridspec_kw is None:

lib/matplotlib/font_manager.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -720,8 +720,7 @@ def set_style(self, style):
720720
"""
721721
if style is None:
722722
style = rcParams['font.style']
723-
if style not in ('normal', 'italic', 'oblique'):
724-
raise ValueError("style must be normal, italic or oblique")
723+
cbook._check_enum(['normal', 'italic', 'oblique'], style=style)
725724
self._slant = style
726725
set_slant = set_style
727726

@@ -731,8 +730,7 @@ def set_variant(self, variant):
731730
"""
732731
if variant is None:
733732
variant = rcParams['font.variant']
734-
if variant not in ('normal', 'small-caps'):
735-
raise ValueError("variant must be normal or small-caps")
733+
cbook._check_enum(['normal', 'small-caps'], variant=variant)
736734
self._variant = variant
737735

738736
def set_weight(self, weight):

lib/matplotlib/mathtext.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3348,14 +3348,10 @@ def parse(self, s, dpi = 72, prop = None):
33483348
font_output = StandardPsFonts(prop)
33493349
else:
33503350
backend = self._backend_mapping[self._output]()
3351-
fontset = rcParams['mathtext.fontset']
3352-
fontset_class = self._font_type_mapping.get(fontset.lower())
3353-
if fontset_class is not None:
3354-
font_output = fontset_class(prop, backend)
3355-
else:
3356-
raise ValueError(
3357-
"mathtext.fontset must be either 'cm', 'dejavuserif', "
3358-
"'dejavusans', 'stix', 'stixsans', or 'custom'")
3351+
fontset = rcParams['mathtext.fontset'].lower()
3352+
cbook._check_enum(self._font_type_mapping, fontset=fontset)
3353+
fontset_class = self._font_type_mapping[fontset]
3354+
font_output = fontset_class(prop, backend)
33593355

33603356
fontsize = prop.get_size_in_points()
33613357

lib/matplotlib/projections/geo.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import numpy as np
22

3-
from matplotlib import rcParams
3+
from matplotlib import cbook, rcParams
44
from matplotlib.axes import Axes
55
import matplotlib.axis as maxis
66
from matplotlib.patches import Circle
@@ -118,9 +118,7 @@ def _get_affine_transform(self):
118118
.translate(0.5, 0.5)
119119

120120
def get_xaxis_transform(self, which='grid'):
121-
if which not in ['tick1', 'tick2', 'grid']:
122-
raise ValueError(
123-
"'which' must be one of 'tick1', 'tick2', or 'grid'")
121+
cbook._check_enum(['tick1', 'tick2', 'grid'], which=which)
124122
return self._xaxis_transform
125123

126124
def get_xaxis_text1_transform(self, pad):
@@ -130,9 +128,7 @@ def get_xaxis_text2_transform(self, pad):
130128
return self._xaxis_text2_transform, 'top', 'center'
131129

132130
def get_yaxis_transform(self, which='grid'):
133-
if which not in ['tick1', 'tick2', 'grid']:
134-
raise ValueError(
135-
"'which' must be one of 'tick1', 'tick2', or 'grid'")
131+
cbook._check_enum(['tick1', 'tick2', 'grid'], which=which)
136132
return self._yaxis_transform
137133

138134
def get_yaxis_text1_transform(self, pad):

lib/matplotlib/projections/polar.py

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33

44
import numpy as np
55

6+
from matplotlib import cbook, rcParams
67
from matplotlib.axes import Axes
78
import matplotlib.axis as maxis
89
import matplotlib.markers as mmarkers
910
import matplotlib.patches as mpatches
1011
import matplotlib.path as mpath
11-
from matplotlib import rcParams
1212
import matplotlib.ticker as mticker
1313
import matplotlib.transforms as mtransforms
1414
import matplotlib.spines as mspines
@@ -969,9 +969,7 @@ def _set_lim_and_transforms(self):
969969
self._r_label_position + self.transData)
970970

971971
def get_xaxis_transform(self, which='grid'):
972-
if which not in ['tick1', 'tick2', 'grid']:
973-
raise ValueError(
974-
"'which' must be one of 'tick1', 'tick2', or 'grid'")
972+
cbook._check_enum(['tick1', 'tick2', 'grid'], which=which)
975973
return self._xaxis_transform
976974

977975
def get_xaxis_text1_transform(self, pad):
@@ -986,8 +984,7 @@ def get_yaxis_transform(self, which='grid'):
986984
elif which == 'grid':
987985
return self._yaxis_transform
988986
else:
989-
raise ValueError(
990-
"'which' must be one of 'tick1', 'tick2', or 'grid'")
987+
cbook._check_enum(['tick1', 'tick2', 'grid'], which=which)
991988

992989
def get_yaxis_text1_transform(self, pad):
993990
thetamin, thetamax = self._realViewLim.intervalx
@@ -1141,15 +1138,14 @@ def set_theta_direction(self, direction):
11411138
Theta increases in the counterclockwise direction
11421139
"""
11431140
mtx = self._direction.get_matrix()
1144-
if direction in ('clockwise',):
1141+
if direction in ('clockwise', -1):
11451142
mtx[0, 0] = -1
1146-
elif direction in ('counterclockwise', 'anticlockwise'):
1143+
elif direction in ('counterclockwise', 'anticlockwise', 1):
11471144
mtx[0, 0] = 1
1148-
elif direction in (1, -1):
1149-
mtx[0, 0] = direction
11501145
else:
1151-
raise ValueError(
1152-
"direction must be 1, -1, clockwise or counterclockwise")
1146+
cbook._check_enum(
1147+
[-1, 1, 'clockwise', 'counterclockwise', 'anticlockwise'],
1148+
direction=direction)
11531149
self._direction.invalidate()
11541150

11551151
def get_theta_direction(self):

lib/matplotlib/quiver.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
import matplotlib.transforms as transforms
2525
import matplotlib.text as mtext
2626
import matplotlib.artist as martist
27-
from matplotlib import docstring
27+
from matplotlib import cbook, docstring
2828
import matplotlib.font_manager as font_manager
2929
from matplotlib.cbook import delete_masked_points
3030
from matplotlib.patches import CirclePolygon
@@ -462,10 +462,7 @@ def __init__(self, ax, *args,
462462
if pivot.lower() == 'mid':
463463
pivot = 'middle'
464464
self.pivot = pivot.lower()
465-
if self.pivot not in self._PIVOT_VALS:
466-
raise ValueError(
467-
'pivot must be one of {keys}, you passed {inp}'.format(
468-
keys=self._PIVOT_VALS, inp=pivot))
465+
cbook._check_enum(self._PIVOT_VALS, pivot=self.pivot)
469466

470467
self.transform = kw.pop('transform', ax.transData)
471468
kw.setdefault('facecolors', self.color)

lib/matplotlib/scale.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -236,19 +236,19 @@ def __init__(self, axis, **kwargs):
236236
base = kwargs.pop('basex', 10.0)
237237
subs = kwargs.pop('subsx', None)
238238
nonpos = kwargs.pop('nonposx', 'clip')
239+
cbook._check_enum(['mask', 'clip'], nonposx=nonpos)
239240
else:
240241
base = kwargs.pop('basey', 10.0)
241242
subs = kwargs.pop('subsy', None)
242243
nonpos = kwargs.pop('nonposy', 'clip')
244+
cbook._check_enum(['mask', 'clip'], nonposy=nonpos)
243245

244246
if len(kwargs):
245247
raise ValueError(("provided too many kwargs, can only pass "
246248
"{'basex', 'subsx', nonposx'} or "
247249
"{'basey', 'subsy', nonposy'}. You passed ") +
248250
"{!r}".format(kwargs))
249251

250-
if nonpos not in ['mask', 'clip']:
251-
raise ValueError("nonposx, nonposy kwarg must be 'mask' or 'clip'")
252252
if base <= 0 or base == 1:
253253
raise ValueError('The log base cannot be <= 0 or == 1')
254254

@@ -511,9 +511,7 @@ def __init__(self, axis, nonpos='mask'):
511511
values beyond ]0, 1[ can be masked as invalid, or clipped to a number
512512
very close to 0 or 1
513513
"""
514-
if nonpos not in ['mask', 'clip']:
515-
raise ValueError("nonposx, nonposy kwarg must be 'mask' or 'clip'")
516-
514+
cbook._check_enum(['mask', 'clip'], nonpos=nonpos)
517515
self._transform = LogitTransform(nonpos)
518516

519517
def get_transform(self):

0 commit comments

Comments
 (0)