diff --git a/lib/matplotlib/_api/__init__.py b/lib/matplotlib/_api/__init__.py index cf27e68a4d2e..f251e07bab59 100644 --- a/lib/matplotlib/_api/__init__.py +++ b/lib/matplotlib/_api/__init__.py @@ -57,6 +57,46 @@ def fget(self): return self._fget +# In the following check_foo() functions, the first parameter starts with an +# underscore because it is intended to be positional-only (e.g., so that +# `_api.check_isinstance([...], types=foo)` doesn't fail. + +def check_isinstance(_types, **kwargs): + """ + For each *key, value* pair in *kwargs*, check that *value* is an instance + of one of *_types*; if not, raise an appropriate TypeError. + + As a special case, a ``None`` entry in *_types* is treated as NoneType. + + Examples + -------- + >>> _api.check_isinstance((SomeClass, None), arg=arg) + """ + types = _types + none_type = type(None) + types = ((types,) if isinstance(types, type) else + (none_type,) if types is None else + tuple(none_type if tp is None else tp for tp in types)) + + def type_name(tp): + return ("None" if tp is none_type + else tp.__qualname__ if tp.__module__ == "builtins" + else f"{tp.__module__}.{tp.__qualname__}") + + for k, v in kwargs.items(): + if not isinstance(v, types): + names = [*map(type_name, types)] + if "None" in names: # Move it to the end for better wording. + names.remove("None") + names.append("None") + raise TypeError( + "{!r} must be an instance of {}, not a {}".format( + k, + ", ".join(names[:-1]) + " or " + names[-1] + if len(names) > 1 else names[0], + type_name(type(v)))) + + def check_in_list(_values, *, _print_supported_values=True, **kwargs): """ For each *key, value* pair in *kwargs*, check that *value* is in *_values*. diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index ae2e0c34141e..a6c6a18a5457 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -1075,7 +1075,7 @@ def sharex(self, other): axes, and cannot be used if the x-axis is already being shared with another axes. """ - cbook._check_isinstance(_AxesBase, other=other) + _api.check_isinstance(_AxesBase, other=other) if self._sharex is not None and other is not self._sharex: raise ValueError("x-axis is already shared") self._shared_x_axes.join(self, other) @@ -1094,7 +1094,7 @@ def sharey(self, other): axes, and cannot be used if the y-axis is already being shared with another axes. """ - cbook._check_isinstance(_AxesBase, other=other) + _api.check_isinstance(_AxesBase, other=other) if self._sharey is not None and other is not self._sharey: raise ValueError("y-axis is already shared") self._shared_y_axes.join(self, other) diff --git a/lib/matplotlib/axis.py b/lib/matplotlib/axis.py index cc68386459a5..7ec16d04d2a2 100644 --- a/lib/matplotlib/axis.py +++ b/lib/matplotlib/axis.py @@ -1599,7 +1599,7 @@ def _set_formatter(self, formatter, level): not isinstance(formatter, mticker.TickHelper)): formatter = mticker.FuncFormatter(formatter) else: - cbook._check_isinstance(mticker.Formatter, formatter=formatter) + _api.check_isinstance(mticker.Formatter, formatter=formatter) if (isinstance(formatter, mticker.FixedFormatter) and len(formatter.seq) > 0 @@ -1624,7 +1624,7 @@ def set_major_locator(self, locator): ---------- locator : `~matplotlib.ticker.Locator` """ - cbook._check_isinstance(mticker.Locator, locator=locator) + _api.check_isinstance(mticker.Locator, locator=locator) self.isDefault_majloc = False self.major.locator = locator if self.major.formatter: @@ -1640,7 +1640,7 @@ def set_minor_locator(self, locator): ---------- locator : `~matplotlib.ticker.Locator` """ - cbook._check_isinstance(mticker.Locator, locator=locator) + _api.check_isinstance(mticker.Locator, locator=locator) self.isDefault_minloc = False self.minor.locator = locator if self.minor.formatter: diff --git a/lib/matplotlib/backend_bases.py b/lib/matplotlib/backend_bases.py index 5a7be04c4815..acbe52d77a3f 100644 --- a/lib/matplotlib/backend_bases.py +++ b/lib/matplotlib/backend_bases.py @@ -930,7 +930,7 @@ def set_clip_rectangle(self, rectangle): def set_clip_path(self, path): """Set the clip path to a `.TransformedPath` or None.""" - cbook._check_isinstance((transforms.TransformedPath, None), path=path) + _api.check_isinstance((transforms.TransformedPath, None), path=path) self._clippath = path def set_dashes(self, dash_offset, dash_list): diff --git a/lib/matplotlib/blocking_input.py b/lib/matplotlib/blocking_input.py index fde7f30c5f38..afbfdacfdbd7 100644 --- a/lib/matplotlib/blocking_input.py +++ b/lib/matplotlib/blocking_input.py @@ -22,7 +22,7 @@ import logging from numbers import Integral -from matplotlib import cbook +from matplotlib import _api from matplotlib.backend_bases import MouseButton import matplotlib.lines as mlines @@ -78,7 +78,7 @@ def pop_event(self, index=-1): def __call__(self, n=1, timeout=30): """Blocking call to retrieve *n* events.""" - cbook._check_isinstance(Integral, n=n) + _api.check_isinstance(Integral, n=n) self.n = n self.events = [] diff --git a/lib/matplotlib/category.py b/lib/matplotlib/category.py index a4df76d438ab..2e7f19cd7a64 100644 --- a/lib/matplotlib/category.py +++ b/lib/matplotlib/category.py @@ -17,7 +17,7 @@ import numpy as np -from matplotlib import cbook, ticker, units +from matplotlib import _api, ticker, units _log = logging.getLogger(__name__) @@ -217,7 +217,7 @@ def update(self, data): convertible = True for val in OrderedDict.fromkeys(data): # OrderedDict just iterates over unique values in data. - cbook._check_isinstance((str, bytes), value=val) + _api.check_isinstance((str, bytes), value=val) if convertible: # this will only be called so long as convertible is True. convertible = self._str_is_convertible(val) diff --git a/lib/matplotlib/cbook/__init__.py b/lib/matplotlib/cbook/__init__.py index db89c9e4a16a..acc1320c3c9c 100644 --- a/lib/matplotlib/cbook/__init__.py +++ b/lib/matplotlib/cbook/__init__.py @@ -2242,47 +2242,6 @@ def _check_and_log_subprocess(command, logger, **kwargs): return proc.stdout -# In the following _check_foo functions, the first parameter starts with an -# underscore because it is intended to be positional-only (e.g., so that -# `_check_isinstance([...], types=foo)` doesn't fail. - - -def _check_isinstance(_types, **kwargs): - """ - For each *key, value* pair in *kwargs*, check that *value* is an instance - of one of *_types*; if not, raise an appropriate TypeError. - - As a special case, a ``None`` entry in *_types* is treated as NoneType. - - Examples - -------- - >>> cbook._check_isinstance((SomeClass, None), arg=arg) - """ - types = _types - none_type = type(None) - types = ((types,) if isinstance(types, type) else - (none_type,) if types is None else - tuple(none_type if tp is None else tp for tp in types)) - - def type_name(tp): - return ("None" if tp is none_type - else tp.__qualname__ if tp.__module__ == "builtins" - else f"{tp.__module__}.{tp.__qualname__}") - - for k, v in kwargs.items(): - if not isinstance(v, types): - names = [*map(type_name, types)] - if "None" in names: # Move it to the end for better wording. - names.remove("None") - names.append("None") - raise TypeError( - "{!r} must be an instance of {}, not a {}".format( - k, - ", ".join(names[:-1]) + " or " + names[-1] - if len(names) > 1 else names[0], - type_name(type(v)))) - - def _backend_module_name(name): """ Convert a backend name (either a standard backend -- "Agg", "TkAgg", ... -- diff --git a/lib/matplotlib/cm.py b/lib/matplotlib/cm.py index 8383b9559416..2f1443d0f09f 100644 --- a/lib/matplotlib/cm.py +++ b/lib/matplotlib/cm.py @@ -136,7 +136,7 @@ def register_cmap(name=None, cmap=None, *, override_builtin=False): the registered colormap will be immutable. """ - cbook._check_isinstance((str, None), name=name) + _api.check_isinstance((str, None), name=name) if name is None: try: name = cmap.name @@ -448,7 +448,7 @@ def set_norm(self, norm): the norm of the mappable will reset the norm, locator, and formatters on the colorbar to default. """ - cbook._check_isinstance((colors.Normalize, None), norm=norm) + _api.check_isinstance((colors.Normalize, None), norm=norm) in_init = self.norm is None if norm is None: norm = colors.Normalize() diff --git a/lib/matplotlib/colorbar.py b/lib/matplotlib/colorbar.py index 96be6cb8edbb..31d9b6176821 100644 --- a/lib/matplotlib/colorbar.py +++ b/lib/matplotlib/colorbar.py @@ -35,7 +35,7 @@ import numpy as np import matplotlib as mpl -from matplotlib import _api, cbook, collections, cm, colors, contour, ticker +from matplotlib import _api, collections, cm, colors, contour, ticker import matplotlib.artist as martist import matplotlib.patches as mpatches import matplotlib.path as mpath @@ -429,7 +429,7 @@ def __init__(self, ax, cmap=None, extendrect=False, label='', ): - cbook._check_isinstance([colors.Colormap, None], cmap=cmap) + _api.check_isinstance([colors.Colormap, None], cmap=cmap) _api.check_in_list( ['vertical', 'horizontal'], orientation=orientation) _api.check_in_list( diff --git a/lib/matplotlib/dviread.py b/lib/matplotlib/dviread.py index 6f65de52b654..b55dacbb2eca 100644 --- a/lib/matplotlib/dviread.py +++ b/lib/matplotlib/dviread.py @@ -551,7 +551,7 @@ class DviFont: __slots__ = ('texname', 'size', 'widths', '_scale', '_vf', '_tfm') def __init__(self, scale, tfm, texname, vf): - cbook._check_isinstance(bytes, texname=texname) + _api.check_isinstance(bytes, texname=texname) self._scale = scale self._tfm = tfm self.texname = texname diff --git a/lib/matplotlib/figure.py b/lib/matplotlib/figure.py index 68d950e6247c..71be82de0374 100644 --- a/lib/matplotlib/figure.py +++ b/lib/matplotlib/figure.py @@ -122,7 +122,7 @@ def add(self, key, a): """ # All the error checking may be unnecessary; but this method # is called so seldom that the overhead is negligible. - cbook._check_isinstance(Axes, a=a) + _api.check_isinstance(Axes, a=a) try: hash(key) except TypeError: diff --git a/lib/matplotlib/rcsetup.py b/lib/matplotlib/rcsetup.py index 3f273cbbee27..e68e6e4809eb 100644 --- a/lib/matplotlib/rcsetup.py +++ b/lib/matplotlib/rcsetup.py @@ -395,7 +395,7 @@ def validate_color(s): def _validate_cmap(s): - cbook._check_isinstance((str, Colormap), cmap=s) + _api.check_isinstance((str, Colormap), cmap=s) return s @@ -770,7 +770,7 @@ def validate_hatch(s): """ if not isinstance(s, str): raise ValueError("Hatch pattern must be a string") - cbook._check_isinstance(str, hatch_pattern=s) + _api.check_isinstance(str, hatch_pattern=s) unknown = set(s) - {'\\', '/', '|', '-', '+', '*', '.', 'x', 'o', 'O'} if unknown: raise ValueError("Unknown hatch symbol(s): %s" % list(unknown)) diff --git a/lib/matplotlib/spines.py b/lib/matplotlib/spines.py index c00962de5a8a..40ceb157fd6e 100644 --- a/lib/matplotlib/spines.py +++ b/lib/matplotlib/spines.py @@ -4,7 +4,7 @@ import numpy as np import matplotlib -from matplotlib import _api, cbook, docstring, rcParams +from matplotlib import _api, docstring, rcParams from matplotlib.artist import allow_rasterization import matplotlib.transforms as mtransforms import matplotlib.patches as mpatches @@ -69,7 +69,7 @@ def __init__(self, axes, spine_type, path, **kwargs): # non-rectangular axes is currently implemented, and this lets # them pass through the spines machinery without errors.) self._position = None - cbook._check_isinstance(matplotlib.path.Path, path=path) + _api.check_isinstance(matplotlib.path.Path, path=path) self._path = path # To support drawing both linear and circular spines, this diff --git a/lib/matplotlib/table.py b/lib/matplotlib/table.py index eea686e4dd63..965cb6eeda9b 100644 --- a/lib/matplotlib/table.py +++ b/lib/matplotlib/table.py @@ -19,7 +19,7 @@ Thanks to John Gill for providing the class and table. """ -from . import artist, cbook, docstring +from . import _api, artist, docstring from .artist import Artist, allow_rasterization from .patches import Rectangle from .text import Text @@ -342,7 +342,7 @@ def __setitem__(self, position, cell): """ Set a custom cell in a given position. """ - cbook._check_isinstance(Cell, cell=cell) + _api.check_isinstance(Cell, cell=cell) try: row, col = position[0], position[1] except Exception as err: diff --git a/lib/matplotlib/transforms.py b/lib/matplotlib/transforms.py index 8fdd49dbd010..bfc2915872c4 100644 --- a/lib/matplotlib/transforms.py +++ b/lib/matplotlib/transforms.py @@ -41,7 +41,7 @@ import numpy as np from numpy.linalg import inv -from matplotlib import _api, cbook +from matplotlib import _api from matplotlib._path import ( affine_transform, count_bboxes_overlapping_bbox, update_path_extents) from .path import Path @@ -1054,7 +1054,7 @@ def __init__(self, bbox, transform, **kwargs): """ if not bbox.is_bbox: raise ValueError("'bbox' is not a bbox") - cbook._check_isinstance(Transform, transform=transform) + _api.check_isinstance(Transform, transform=transform) if transform.input_dims != 2 or transform.output_dims != 2: raise ValueError( "The input and output dimensions of 'transform' must be 2") @@ -1660,7 +1660,7 @@ def __init__(self, child): *child*: A `Transform` instance. This child may later be replaced with :meth:`set`. """ - cbook._check_isinstance(Transform, child=child) + _api.check_isinstance(Transform, child=child) self._init(child) self.set_children(child) @@ -1911,7 +1911,7 @@ def set(self, other): Set this transformation from the frozen copy of another `Affine2DBase` object. """ - cbook._check_isinstance(Affine2DBase, other=other) + _api.check_isinstance(Affine2DBase, other=other) self._mtx = other.get_matrix() self.invalidate() @@ -2686,7 +2686,7 @@ def __init__(self, path, transform): path : `~.path.Path` transform : `Transform` """ - cbook._check_isinstance(Transform, transform=transform) + _api.check_isinstance(Transform, transform=transform) super().__init__() self._path = path self._transform = transform diff --git a/lib/matplotlib/tri/trifinder.py b/lib/matplotlib/tri/trifinder.py index 8cf3830125eb..e06b84c0d974 100644 --- a/lib/matplotlib/tri/trifinder.py +++ b/lib/matplotlib/tri/trifinder.py @@ -1,6 +1,6 @@ import numpy as np -from matplotlib import cbook +from matplotlib import _api from matplotlib.tri import Triangulation @@ -17,7 +17,7 @@ class TriFinder: """ def __init__(self, triangulation): - cbook._check_isinstance(Triangulation, triangulation=triangulation) + _api.check_isinstance(Triangulation, triangulation=triangulation) self._triangulation = triangulation diff --git a/lib/matplotlib/tri/triinterpolate.py b/lib/matplotlib/tri/triinterpolate.py index 8c649d5c27fc..84674766f04d 100644 --- a/lib/matplotlib/tri/triinterpolate.py +++ b/lib/matplotlib/tri/triinterpolate.py @@ -4,7 +4,7 @@ import numpy as np -from matplotlib import _api, cbook +from matplotlib import _api from matplotlib.tri import Triangulation from matplotlib.tri.trifinder import TriFinder from matplotlib.tri.tritools import TriAnalyzer @@ -31,7 +31,7 @@ class TriInterpolator: """ def __init__(self, triangulation, z, trifinder=None): - cbook._check_isinstance(Triangulation, triangulation=triangulation) + _api.check_isinstance(Triangulation, triangulation=triangulation) self._triangulation = triangulation self._z = np.asarray(z) @@ -39,7 +39,7 @@ def __init__(self, triangulation, z, trifinder=None): raise ValueError("z array must have same length as triangulation x" " and y arrays") - cbook._check_isinstance((TriFinder, None), trifinder=trifinder) + _api.check_isinstance((TriFinder, None), trifinder=trifinder) self._trifinder = trifinder or self._triangulation.get_trifinder() # Default scaling factors : 1.0 (= no scaling) @@ -996,8 +996,7 @@ class _DOF_estimator: gradient coordinates. """ def __init__(self, interpolator, **kwargs): - cbook._check_isinstance( - CubicTriInterpolator, interpolator=interpolator) + _api.check_isinstance(CubicTriInterpolator, interpolator=interpolator) self._pts = interpolator._pts self._tris_pts = interpolator._tris_pts self.z = interpolator._z diff --git a/lib/matplotlib/tri/tripcolor.py b/lib/matplotlib/tri/tripcolor.py index 67cb0f3c9079..f1f7de2285dc 100644 --- a/lib/matplotlib/tri/tripcolor.py +++ b/lib/matplotlib/tri/tripcolor.py @@ -1,6 +1,6 @@ import numpy as np -from matplotlib import _api, cbook +from matplotlib import _api from matplotlib.collections import PolyCollection, TriMesh from matplotlib.colors import Normalize from matplotlib.tri.triangulation import Triangulation @@ -114,7 +114,7 @@ def tripcolor(ax, *args, alpha=1.0, norm=None, cmap=None, vmin=None, collection.set_alpha(alpha) collection.set_array(C) - cbook._check_isinstance((Normalize, None), norm=norm) + _api.check_isinstance((Normalize, None), norm=norm) collection.set_cmap(cmap) collection.set_norm(norm) collection._scale_norm(norm, vmin, vmax) diff --git a/lib/matplotlib/tri/trirefine.py b/lib/matplotlib/tri/trirefine.py index b253dbaaca8e..7ba66d0ea5c6 100644 --- a/lib/matplotlib/tri/trirefine.py +++ b/lib/matplotlib/tri/trirefine.py @@ -4,7 +4,7 @@ import numpy as np -from matplotlib import cbook +from matplotlib import _api from matplotlib.tri.triangulation import Triangulation import matplotlib.tri.triinterpolate @@ -40,7 +40,7 @@ class TriRefiner: """ def __init__(self, triangulation): - cbook._check_isinstance(Triangulation, triangulation=triangulation) + _api.check_isinstance(Triangulation, triangulation=triangulation) self._triangulation = triangulation @@ -158,8 +158,8 @@ def refine_field(self, z, triinterpolator=None, subdiv=3): interp = matplotlib.tri.CubicTriInterpolator( self._triangulation, z) else: - cbook._check_isinstance(matplotlib.tri.TriInterpolator, - triinterpolator=triinterpolator) + _api.check_isinstance(matplotlib.tri.TriInterpolator, + triinterpolator=triinterpolator) interp = triinterpolator refi_tri, found_index = self.refine_triangulation( diff --git a/lib/matplotlib/tri/tritools.py b/lib/matplotlib/tri/tritools.py index 90a9db8461a5..bda8f7c0248f 100644 --- a/lib/matplotlib/tri/tritools.py +++ b/lib/matplotlib/tri/tritools.py @@ -4,7 +4,7 @@ import numpy as np -from matplotlib import cbook +from matplotlib import _api from matplotlib.tri import Triangulation @@ -26,7 +26,7 @@ class TriAnalyzer: """ def __init__(self, triangulation): - cbook._check_isinstance(Triangulation, triangulation=triangulation) + _api.check_isinstance(Triangulation, triangulation=triangulation) self._triangulation = triangulation @property diff --git a/lib/mpl_toolkits/axes_grid1/axes_size.py b/lib/mpl_toolkits/axes_grid1/axes_size.py index 541ec7f64959..87bc2419e1b4 100644 --- a/lib/mpl_toolkits/axes_grid1/axes_size.py +++ b/lib/mpl_toolkits/axes_grid1/axes_size.py @@ -11,7 +11,7 @@ class (or others) to determine the size of each axes. The unit from numbers import Number -from matplotlib import _api, cbook +from matplotlib import _api from matplotlib.axes import Axes @@ -54,7 +54,7 @@ class Fixed(_Base): """ def __init__(self, fixed_size): - cbook._check_isinstance(Number, fixed_size=fixed_size) + _api.check_isinstance(Number, fixed_size=fixed_size) self.fixed_size = fixed_size def get_size(self, renderer): @@ -189,7 +189,7 @@ class Fraction(_Base): """ def __init__(self, fraction, ref_size): - cbook._check_isinstance(Number, fraction=fraction) + _api.check_isinstance(Number, fraction=fraction) self._fraction_ref = ref_size self._fraction = fraction