Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit a2ff624

Browse filesBrowse files
authored
Merge pull request #14470 from anntzer/check_isinstance
MNT/API: Add _check_isinstance helper.
2 parents 5a3276f + 63b7515 commit a2ff624
Copy full SHA for a2ff624
Expand file treeCollapse file tree

19 files changed

+83
-94
lines changed
+9Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
Exception changes
2+
`````````````````
3+
4+
Various APIs that raised a `ValueError` for incorrectly typed inputs now raise
5+
`TypeError` instead: `backend_bases.GraphicsContextBase.set_clip_path`,
6+
`blocking_input.BlockingInput.__call__`, `cm.register_cmap`, `dviread.DviFont`,
7+
`rcsetup.validate_hatch`, `rcsetup.validate_animation_writer_path`, `spines.Spine`,
8+
many classes in the :mod:`matplotlib.transforms` module and :mod:`matplotlib.tri`
9+
package, and Axes methods that take a ``norm`` parameter.

‎lib/matplotlib/axes/_axes.py

Copy file name to clipboardExpand all lines: lib/matplotlib/axes/_axes.py
-21Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4454,9 +4454,6 @@ def scatter(self, x, y, s=None, c=None, marker=None, cmap=None, norm=None,
44544454
collection.update(kwargs)
44554455

44564456
if colors is None:
4457-
if norm is not None and not isinstance(norm, mcolors.Normalize):
4458-
raise ValueError(
4459-
"'norm' must be an instance of 'mcolors.Normalize'")
44604457
collection.set_array(c)
44614458
collection.set_cmap(cmap)
44624459
collection.set_norm(norm)
@@ -4770,11 +4767,6 @@ def hexbin(self, x, y, C=None, gridsize=100, bins=None,
47704767
offset_position="data"
47714768
)
47724769

4773-
# Check for valid norm
4774-
if norm is not None and not isinstance(norm, mcolors.Normalize):
4775-
msg = "'norm' must be an instance of 'mcolors.Normalize'"
4776-
raise ValueError(msg)
4777-
47784770
# Set normalizer if bins is 'log'
47794771
if bins == 'log':
47804772
if norm is not None:
@@ -5593,9 +5585,6 @@ def imshow(self, X, cmap=None, norm=None, aspect=None,
55935585
`~matplotlib.pyplot.imshow` expects RGB images adopting the straight
55945586
(unassociated) alpha representation.
55955587
"""
5596-
if norm is not None and not isinstance(norm, mcolors.Normalize):
5597-
raise ValueError(
5598-
"'norm' must be an instance of 'mcolors.Normalize'")
55995588
if aspect is None:
56005589
aspect = rcParams['image.aspect']
56015590
self.set_aspect(aspect)
@@ -5885,9 +5874,6 @@ def pcolor(self, *args, alpha=None, norm=None, cmap=None, vmin=None,
58855874

58865875
collection.set_alpha(alpha)
58875876
collection.set_array(C)
5888-
if norm is not None and not isinstance(norm, mcolors.Normalize):
5889-
raise ValueError(
5890-
"'norm' must be an instance of 'mcolors.Normalize'")
58915877
collection.set_cmap(cmap)
58925878
collection.set_norm(norm)
58935879
collection.set_clim(vmin, vmax)
@@ -6102,9 +6088,6 @@ def pcolormesh(self, *args, alpha=None, norm=None, cmap=None, vmin=None,
61026088
**kwargs)
61036089
collection.set_alpha(alpha)
61046090
collection.set_array(C)
6105-
if norm is not None and not isinstance(norm, mcolors.Normalize):
6106-
raise ValueError(
6107-
"'norm' must be an instance of 'mcolors.Normalize'")
61086091
collection.set_cmap(cmap)
61096092
collection.set_norm(norm)
61106093
collection.set_clim(vmin, vmax)
@@ -6241,11 +6224,7 @@ def pcolorfast(self, *args, alpha=None, norm=None, cmap=None, vmin=None,
62416224
Notes
62426225
-----
62436226
.. [notes section required to get data note injection right]
6244-
62456227
"""
6246-
if norm is not None and not isinstance(norm, mcolors.Normalize):
6247-
raise ValueError(
6248-
"'norm' must be an instance of 'mcolors.Normalize'")
62496228

62506229
C = args[-1]
62516230
nr, nc = np.shape(C)[:2]

‎lib/matplotlib/axis.py

Copy file name to clipboardExpand all lines: lib/matplotlib/axis.py
+4-12Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1631,9 +1631,7 @@ def set_major_formatter(self, formatter):
16311631
----------
16321632
formatter : `~matplotlib.ticker.Formatter`
16331633
"""
1634-
if not isinstance(formatter, mticker.Formatter):
1635-
raise TypeError("formatter argument should be instance of "
1636-
"matplotlib.ticker.Formatter")
1634+
cbook._check_isinstance(mticker.Formatter, formatter=formatter)
16371635
self.isDefault_majfmt = False
16381636
self.major.formatter = formatter
16391637
formatter.set_axis(self)
@@ -1647,9 +1645,7 @@ def set_minor_formatter(self, formatter):
16471645
----------
16481646
formatter : `~matplotlib.ticker.Formatter`
16491647
"""
1650-
if not isinstance(formatter, mticker.Formatter):
1651-
raise TypeError("formatter argument should be instance of "
1652-
"matplotlib.ticker.Formatter")
1648+
cbook._check_isinstance(mticker.Formatter, formatter=formatter)
16531649
self.isDefault_minfmt = False
16541650
self.minor.formatter = formatter
16551651
formatter.set_axis(self)
@@ -1663,9 +1659,7 @@ def set_major_locator(self, locator):
16631659
----------
16641660
locator : `~matplotlib.ticker.Locator`
16651661
"""
1666-
if not isinstance(locator, mticker.Locator):
1667-
raise TypeError("locator argument should be instance of "
1668-
"matplotlib.ticker.Locator")
1662+
cbook._check_isinstance(mticker.Locator, locator=locator)
16691663
self.isDefault_majloc = False
16701664
self.major.locator = locator
16711665
if self.major.formatter:
@@ -1681,9 +1675,7 @@ def set_minor_locator(self, locator):
16811675
----------
16821676
locator : `~matplotlib.ticker.Locator`
16831677
"""
1684-
if not isinstance(locator, mticker.Locator):
1685-
raise TypeError("locator argument should be instance of "
1686-
"matplotlib.ticker.Locator")
1678+
cbook._check_isinstance(mticker.Locator, locator=locator)
16871679
self.isDefault_minloc = False
16881680
self.minor.locator = locator
16891681
if self.minor.formatter:

‎lib/matplotlib/backend_bases.py

Copy file name to clipboardExpand all lines: lib/matplotlib/backend_bases.py
+6-6Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -879,13 +879,13 @@ def set_clip_rectangle(self, rectangle):
879879

880880
def set_clip_path(self, path):
881881
"""
882-
Set the clip path and transformation. Path should be a
883-
:class:`~matplotlib.transforms.TransformedPath` instance.
882+
Set the clip path and transformation.
883+
884+
Parameters
885+
----------
886+
path : `~matplotlib.transforms.TransformedPath` or None
884887
"""
885-
if (path is not None
886-
and not isinstance(path, transforms.TransformedPath)):
887-
raise ValueError("Path should be a "
888-
"matplotlib.transforms.TransformedPath instance")
888+
cbook._check_isinstance((transforms.TransformedPath, None), path=path)
889889
self._clippath = path
890890

891891
def set_dashes(self, dash_offset, dash_list):

‎lib/matplotlib/blocking_input.py

Copy file name to clipboardExpand all lines: lib/matplotlib/blocking_input.py
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import logging
2323
from numbers import Integral
2424

25+
from matplotlib import cbook
2526
import matplotlib.lines as mlines
2627

2728
_log = logging.getLogger(__name__)
@@ -76,8 +77,7 @@ def pop_event(self, index=-1):
7677

7778
def __call__(self, n=1, timeout=30):
7879
"""Blocking call to retrieve *n* events."""
79-
if not isinstance(n, Integral):
80-
raise ValueError("Requires an integer argument")
80+
cbook._check_isinstance(Integral, n=n)
8181
self.n = n
8282
self.events = []
8383

‎lib/matplotlib/category.py

Copy file name to clipboardExpand all lines: lib/matplotlib/category.py
+2-4Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@
1717

1818
import numpy as np
1919

20-
import matplotlib.units as units
21-
import matplotlib.ticker as ticker
20+
from matplotlib import cbook, ticker, units
2221

2322

2423
_log = logging.getLogger(__name__)
@@ -204,8 +203,7 @@ def update(self, data):
204203
convertible = True
205204
for val in OrderedDict.fromkeys(data):
206205
# OrderedDict just iterates over unique values in data.
207-
if not isinstance(val, (str, bytes)):
208-
raise TypeError("{val!r} is not a string".format(val=val))
206+
cbook._check_isinstance((str, bytes), value=val)
209207
if convertible:
210208
# this will only be called so long as convertible is True.
211209
convertible = self._str_is_convertible(val)

‎lib/matplotlib/cbook/__init__.py

Copy file name to clipboardExpand all lines: lib/matplotlib/cbook/__init__.py
+34Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2011,6 +2011,40 @@ def _check_and_log_subprocess(command, logger, **kwargs):
20112011
return report
20122012

20132013

2014+
def _check_isinstance(types, **kwargs):
2015+
"""
2016+
For each *key, value* pair in *kwargs*, check that *value* is an instance
2017+
of one of *types*; if not, raise an appropriate TypeError.
2018+
2019+
As a special case, a ``None`` entry in *types* is treated as NoneType.
2020+
2021+
Examples
2022+
--------
2023+
>>> cbook._check_isinstance((SomeClass, None), arg=arg)
2024+
"""
2025+
if isinstance(types, type) or types is None:
2026+
types = (types,)
2027+
none_allowed = None in types
2028+
types = tuple(tp for tp in types if tp is not None)
2029+
2030+
def type_name(tp):
2031+
return (tp.__qualname__ if tp.__module__ == "builtins"
2032+
else f"{tp.__module__}.{tp.__qualname__}")
2033+
2034+
names = [*map(type_name, types)]
2035+
if none_allowed:
2036+
types = (*types, type(None))
2037+
names.append("None")
2038+
for k, v in kwargs.items():
2039+
if not isinstance(v, types):
2040+
raise TypeError(
2041+
"{!r} must be an instance of {}, not a {}".format(
2042+
k,
2043+
", ".join(names[:-1]) + " or " + names[-1]
2044+
if len(names) > 1 else names[0],
2045+
type_name(type(v))))
2046+
2047+
20142048
def _check_in_list(values, **kwargs):
20152049
"""
20162050
For each *key, value* pair in *kwargs*, check that *value* is in *values*;

‎lib/matplotlib/cm.py

Copy file name to clipboardExpand all lines: lib/matplotlib/cm.py
+2-6Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -130,21 +130,16 @@ def register_cmap(name=None, cmap=None, data=None, lut=None):
130130
In the second case, the three arguments are passed to
131131
the :class:`~matplotlib.colors.LinearSegmentedColormap` initializer,
132132
and the resulting colormap is registered.
133-
134133
"""
134+
cbook._check_isinstance((str, None), name=name)
135135
if name is None:
136136
try:
137137
name = cmap.name
138138
except AttributeError:
139139
raise ValueError("Arguments must include a name or a Colormap")
140-
141-
if not isinstance(name, str):
142-
raise ValueError("Colormap name must be a string")
143-
144140
if isinstance(cmap, colors.Colormap):
145141
cmap_d[name] = cmap
146142
return
147-
148143
# For the remainder, let exceptions propagate.
149144
if lut is None:
150145
lut = mpl.rcParams['image.lut']
@@ -365,6 +360,7 @@ def set_norm(self, norm):
365360
on the colorbar to default.
366361
367362
"""
363+
cbook._check_isinstance((colors.Normalize, None), norm=norm)
368364
if norm is None:
369365
norm = colors.Normalize()
370366
self.norm = norm

‎lib/matplotlib/dviread.py

Copy file name to clipboardExpand all lines: lib/matplotlib/dviread.py
+1-3Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -525,9 +525,7 @@ class DviFont:
525525
__slots__ = ('texname', 'size', 'widths', '_scale', '_vf', '_tfm')
526526

527527
def __init__(self, scale, tfm, texname, vf):
528-
if not isinstance(texname, bytes):
529-
raise ValueError("texname must be a bytestring, got %s"
530-
% type(texname))
528+
cbook._check_isinstance(bytes, texname=texname)
531529
self._scale = scale
532530
self._tfm = tfm
533531
self.texname = texname

‎lib/matplotlib/figure.py

Copy file name to clipboardExpand all lines: lib/matplotlib/figure.py
+1-2Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,7 @@ def add(self, key, a):
123123
"""
124124
# All the error checking may be unnecessary; but this method
125125
# is called so seldom that the overhead is negligible.
126-
if not isinstance(a, Axes):
127-
raise ValueError("second argument, {!r}, is not an Axes".format(a))
126+
cbook._check_isinstance(Axes, a=a)
128127
try:
129128
hash(key)
130129
except TypeError:

‎lib/matplotlib/rcsetup.py

Copy file name to clipboardExpand all lines: lib/matplotlib/rcsetup.py
+2-3Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -738,10 +738,10 @@ def validate_hatch(s):
738738
Validate a hatch pattern.
739739
A hatch pattern string can have any sequence of the following
740740
characters: ``\ / | - + * . x o O``.
741-
742741
"""
743742
if not isinstance(s, str):
744743
raise ValueError("Hatch pattern must be a string")
744+
cbook._check_isinstance(str, hatch_pattern=s)
745745
unknown = set(s) - {'\\', '/', '|', '-', '+', '*', '.', 'x', 'o', 'O'}
746746
if unknown:
747747
raise ValueError("Unknown hatch symbol(s): %s" % list(unknown))
@@ -955,8 +955,7 @@ def validate_animation_writer_path(p):
955955
# Make sure it's a string and then figure out if the animations
956956
# are already loaded and reset the writers (which will validate
957957
# the path on next call)
958-
if not isinstance(p, str):
959-
raise ValueError("path must be a (unicode) string")
958+
cbook._check_isinstance(str, path=p)
960959
from sys import modules
961960
# set dirty, so that the next call to the registry will re-evaluate
962961
# the state.

‎lib/matplotlib/spines.py

Copy file name to clipboardExpand all lines: lib/matplotlib/spines.py
+1-3Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,7 @@ def __init__(self, axes, spine_type, path, **kwargs):
6262
# non-rectangular axes is currently implemented, and this lets
6363
# them pass through the spines machinery without errors.)
6464
self._position = None
65-
if not isinstance(path, matplotlib.path.Path):
66-
raise ValueError(
67-
"'path' must be an instance of 'matplotlib.path.Path'")
65+
cbook._check_isinstance(matplotlib.path.Path, path=path)
6866
self._path = path
6967

7068
# To support drawing both linear and circular spines, this

‎lib/matplotlib/table.py

Copy file name to clipboardExpand all lines: lib/matplotlib/table.py
+1-2Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -360,8 +360,7 @@ def __setitem__(self, position, cell):
360360
"""
361361
Set a custom cell in a given position.
362362
"""
363-
if not isinstance(cell, CustomCell):
364-
raise TypeError('Table only accepts CustomCell')
363+
cbook._check_isinstance(CustomCell, cell=cell)
365364
try:
366365
row, col = position[0], position[1]
367366
except Exception:

‎lib/matplotlib/transforms.py

Copy file name to clipboardExpand all lines: lib/matplotlib/transforms.py
+4-13Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -989,9 +989,7 @@ def __init__(self, bbox, transform, **kwargs):
989989
"""
990990
if not bbox.is_bbox:
991991
raise ValueError("'bbox' is not a bbox")
992-
if not isinstance(transform, Transform):
993-
raise ValueError("'transform' must be an instance of "
994-
"'matplotlib.transform.Transform'")
992+
cbook._check_isinstance(Transform, transform=transform)
995993
if transform.input_dims != 2 or transform.output_dims != 2:
996994
raise ValueError(
997995
"The input and output dimensions of 'transform' must be 2")
@@ -1586,9 +1584,7 @@ def __init__(self, child):
15861584
*child*: A class:`Transform` instance. This child may later
15871585
be replaced with :meth:`set`.
15881586
"""
1589-
if not isinstance(child, Transform):
1590-
raise ValueError("'child' must be an instance of "
1591-
"'matplotlib.transform.Transform'")
1587+
cbook._check_isinstance(Transform, child=child)
15921588
self._init(child)
15931589
self.set_children(child)
15941590

@@ -1864,9 +1860,7 @@ def set(self, other):
18641860
Set this transformation from the frozen copy of another
18651861
:class:`Affine2DBase` object.
18661862
"""
1867-
if not isinstance(other, Affine2DBase):
1868-
raise ValueError("'other' must be an instance of "
1869-
"'matplotlib.transform.Affine2DBase'")
1863+
cbook._check_isinstance(Affine2DBase, other=other)
18701864
self._mtx = other.get_matrix()
18711865
self.invalidate()
18721866

@@ -2655,11 +2649,8 @@ def __init__(self, path, transform):
26552649
path : `~.path.Path`
26562650
transform : `Transform`
26572651
"""
2658-
if not isinstance(transform, Transform):
2659-
raise ValueError("'transform' must be an instance of "
2660-
"'matplotlib.transform.Transform'")
2652+
cbook._check_isinstance(Transform, transform=transform)
26612653
TransformNode.__init__(self)
2662-
26632654
self._path = path
26642655
self._transform = transform
26652656
self.set_children(transform)

‎lib/matplotlib/tri/trifinder.py

Copy file name to clipboardExpand all lines: lib/matplotlib/tri/trifinder.py
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import numpy as np
22

3+
from matplotlib import cbook
34
from matplotlib.tri import Triangulation
45

56

@@ -16,8 +17,7 @@ class TriFinder:
1617
coordinates of the same shape.
1718
"""
1819
def __init__(self, triangulation):
19-
if not isinstance(triangulation, Triangulation):
20-
raise ValueError('Expected a Triangulation object')
20+
cbook._check_isinstance(Triangulation, triangulation=triangulation)
2121
self._triangulation = triangulation
2222

2323

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.