diff --git a/doc/api/next_api_changes/deprecations/22148-OG.rst b/doc/api/next_api_changes/deprecations/22148-OG.rst new file mode 100644 index 000000000000..70a59ba39042 --- /dev/null +++ b/doc/api/next_api_changes/deprecations/22148-OG.rst @@ -0,0 +1,5 @@ +Module ``docstring`` deprecated +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The module ``matplotlib.docstring`` is considered internal and public access +is deprecated. diff --git a/doc/api/prev_api_changes/api_changes_3.5.0/removals.rst b/doc/api/prev_api_changes/api_changes_3.5.0/removals.rst index cc81bd702918..3ea9b338026d 100644 --- a/doc/api/prev_api_changes/api_changes_3.5.0/removals.rst +++ b/doc/api/prev_api_changes/api_changes_3.5.0/removals.rst @@ -214,7 +214,7 @@ The following class methods have been removed: - ``Colorbar.on_mappable_changed`` and ``Colorbar.update_bruteforce``; use ``Colorbar.update_normal()`` instead - ``docstring.Substitution.from_params`` has been removed; directly assign to - ``params`` of `.Substitution` instead + ``params`` of ``docstring.Substitution`` instead - ``DraggableBase.artist_picker``; set the artist's picker instead - ``DraggableBase.on_motion_blit``; use `.DraggableBase.on_motion` instead - ``FigureCanvasGTK3._renderer_init`` diff --git a/doc/devel/documenting_mpl.rst b/doc/devel/documenting_mpl.rst index 356b223717d5..2f144b44321e 100644 --- a/doc/devel/documenting_mpl.rst +++ b/doc/devel/documenting_mpl.rst @@ -684,14 +684,14 @@ are: 2. as automated as possible so that as properties change, the docs are updated automatically. -The ``@docstring.interpd`` decorator implements this. Any function accepting +The ``@_docstring.interpd`` decorator implements this. Any function accepting `.Line2D` pass-through ``kwargs``, e.g., `matplotlib.axes.Axes.plot`, can list a summary of the `.Line2D` properties, as follows: .. code-block:: python # in axes.py - @docstring.interpd + @_docstring.interpd def plot(self, *args, **kwargs): """ Some stuff omitted @@ -726,7 +726,7 @@ gets interpolated into the docstring. Note that this scheme does not work for decorating an Artist's ``__init__``, as the subclass and its properties are not defined yet at that point. Instead, -``@docstring.interpd`` can be used to decorate the class itself -- at that +``@_docstring.interpd`` can be used to decorate the class itself -- at that point, `.kwdoc` can list the properties and interpolate them into ``__init__.__doc__``. diff --git a/lib/matplotlib/__init__.py b/lib/matplotlib/__init__.py index 3dbf09a3f12c..9a90b73933fd 100644 --- a/lib/matplotlib/__init__.py +++ b/lib/matplotlib/__init__.py @@ -106,7 +106,7 @@ # cbook must import matplotlib only within function # definitions, so it is safe to import from it here. -from . import _api, _version, cbook, docstring, rcsetup +from . import _api, _version, cbook, _docstring, rcsetup from matplotlib.cbook import sanitize_sequence from matplotlib._api import MatplotlibDeprecationWarning from matplotlib.rcsetup import validate_backend, cycler @@ -593,7 +593,7 @@ def gen_candidates(): _deprecated_remain_as_none = {} -@docstring.Substitution( +@_docstring.Substitution( "\n".join(map("- {}".format, sorted(rcsetup._validators, key=str.lower))) ) class RcParams(MutableMapping, dict): diff --git a/lib/matplotlib/_docstring.py b/lib/matplotlib/_docstring.py new file mode 100644 index 000000000000..1beb6a17eb2a --- /dev/null +++ b/lib/matplotlib/_docstring.py @@ -0,0 +1,97 @@ +import inspect + +from . import _api + + +class Substitution: + """ + A decorator that performs %-substitution on an object's docstring. + + This decorator should be robust even if ``obj.__doc__`` is None (for + example, if -OO was passed to the interpreter). + + Usage: construct a docstring.Substitution with a sequence or dictionary + suitable for performing substitution; then decorate a suitable function + with the constructed object, e.g.:: + + sub_author_name = Substitution(author='Jason') + + @sub_author_name + def some_function(x): + "%(author)s wrote this function" + + # note that some_function.__doc__ is now "Jason wrote this function" + + One can also use positional arguments:: + + sub_first_last_names = Substitution('Edgar Allen', 'Poe') + + @sub_first_last_names + def some_function(x): + "%s %s wrote the Raven" + """ + def __init__(self, *args, **kwargs): + if args and kwargs: + raise TypeError("Only positional or keyword args are allowed") + self.params = params = args or kwargs + + def __call__(self, func): + if func.__doc__: + func.__doc__ = inspect.cleandoc(func.__doc__) % self.params + return func + + def update(self, *args, **kwargs): + """ + Update ``self.params`` (which must be a dict) with the supplied args. + """ + self.params.update(*args, **kwargs) + + +class _ArtistKwdocLoader(dict): + def __missing__(self, key): + if not key.endswith(":kwdoc"): + raise KeyError(key) + name = key[:-len(":kwdoc")] + from matplotlib.artist import Artist, kwdoc + try: + cls, = [cls for cls in _api.recursive_subclasses(Artist) + if cls.__name__ == name] + except ValueError as e: + raise KeyError(key) from e + return self.setdefault(key, kwdoc(cls)) + + +class _ArtistPropertiesSubstitution(Substitution): + """ + A `.Substitution` with two additional features: + + - Substitutions of the form ``%(classname:kwdoc)s`` (ending with the + literal ":kwdoc" suffix) trigger lookup of an Artist subclass with the + given *classname*, and are substituted with the `.kwdoc` of that class. + - Decorating a class triggers substitution both on the class docstring and + on the class' ``__init__`` docstring (which is a commonly required + pattern for Artist subclasses). + """ + + def __init__(self): + self.params = _ArtistKwdocLoader() + + def __call__(self, obj): + super().__call__(obj) + if isinstance(obj, type) and obj.__init__ != object.__init__: + self(obj.__init__) + return obj + + +def copy(source): + """Copy a docstring from another source function (if present).""" + def do_copy(target): + if source.__doc__: + target.__doc__ = source.__doc__ + return target + return do_copy + + +# Create a decorator that will house the various docstring snippets reused +# throughout Matplotlib. +dedent_interpd = interpd = _ArtistPropertiesSubstitution() diff --git a/lib/matplotlib/_enums.py b/lib/matplotlib/_enums.py index b15956babbab..c8c50f7c3028 100644 --- a/lib/matplotlib/_enums.py +++ b/lib/matplotlib/_enums.py @@ -11,7 +11,7 @@ """ from enum import Enum, auto -from matplotlib import docstring +from matplotlib import _docstring class _AutoStringNameEnum(Enum): @@ -181,5 +181,5 @@ def demo(): + ", ".join([f"'{cs.name}'" for cs in CapStyle]) \ + "}" -docstring.interpd.update({'JoinStyle': JoinStyle.input_description, +_docstring.interpd.update({'JoinStyle': JoinStyle.input_description, 'CapStyle': CapStyle.input_description}) diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py index 3026e681f742..09daf8950a6d 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -13,7 +13,6 @@ import matplotlib.colors as mcolors import matplotlib.contour as mcontour import matplotlib.dates # Register date unit converter as side-effect. -import matplotlib.docstring as docstring import matplotlib.image as mimage import matplotlib.legend as mlegend import matplotlib.lines as mlines @@ -30,7 +29,7 @@ import matplotlib.transforms as mtransforms import matplotlib.tri as mtri import matplotlib.units as munits -from matplotlib import _api, _preprocess_data, rcParams +from matplotlib import _api, _docstring, _preprocess_data, rcParams from matplotlib.axes._base import ( _AxesBase, _TransformedBoundsLocator, _process_plot_format) from matplotlib.axes._secondary_axes import SecondaryAxis @@ -43,7 +42,7 @@ # All the other methods should go in the _AxesBase class. -@docstring.interpd +@_docstring.interpd class Axes(_AxesBase): """ The `Axes` contains most of the figure elements: `~.axis.Axis`, @@ -183,7 +182,7 @@ def get_legend_handles_labels(self, legend_handler_map=None): [self], legend_handler_map) return handles, labels - @docstring.dedent_interpd + @_docstring.dedent_interpd def legend(self, *args, **kwargs): """ Place a legend on the Axes. @@ -367,7 +366,7 @@ def inset_axes(self, bounds, *, transform=None, zorder=5, **kwargs): return inset_ax - @docstring.dedent_interpd + @_docstring.dedent_interpd def indicate_inset(self, bounds, inset_ax=None, *, transform=None, facecolor='none', edgecolor='0.5', alpha=0.5, zorder=4.99, **kwargs): @@ -519,7 +518,7 @@ def indicate_inset_zoom(self, inset_ax, **kwargs): rect = (xlim[0], ylim[0], xlim[1] - xlim[0], ylim[1] - ylim[0]) return self.indicate_inset(rect, inset_ax, **kwargs) - @docstring.dedent_interpd + @_docstring.dedent_interpd def secondary_xaxis(self, location, *, functions=None, **kwargs): """ Add a second x-axis to this Axes. @@ -561,7 +560,7 @@ def invert(x): raise ValueError('secondary_xaxis location must be either ' 'a float or "top"/"bottom"') - @docstring.dedent_interpd + @_docstring.dedent_interpd def secondary_yaxis(self, location, *, functions=None, **kwargs): """ Add a second y-axis to this Axes. @@ -593,7 +592,7 @@ def secondary_yaxis(self, location, *, functions=None, **kwargs): raise ValueError('secondary_yaxis location must be either ' 'a float or "left"/"right"') - @docstring.dedent_interpd + @_docstring.dedent_interpd def text(self, x, y, s, fontdict=None, **kwargs): """ Add text to the Axes. @@ -661,7 +660,7 @@ def text(self, x, y, s, fontdict=None, **kwargs): self._add_text(t) return t - @docstring.dedent_interpd + @_docstring.dedent_interpd def annotate(self, text, xy, xytext=None, xycoords='data', textcoords=None, arrowprops=None, annotation_clip=None, **kwargs): # Signature must match Annotation. This is verified in @@ -677,7 +676,7 @@ def annotate(self, text, xy, xytext=None, xycoords='data', textcoords=None, annotate.__doc__ = mtext.Annotation.__init__.__doc__ #### Lines and spans - @docstring.dedent_interpd + @_docstring.dedent_interpd def axhline(self, y=0, xmin=0, xmax=1, **kwargs): """ Add a horizontal line across the Axes. @@ -745,7 +744,7 @@ def axhline(self, y=0, xmin=0, xmax=1, **kwargs): self._request_autoscale_view("y") return l - @docstring.dedent_interpd + @_docstring.dedent_interpd def axvline(self, x=0, ymin=0, ymax=1, **kwargs): """ Add a vertical line across the Axes. @@ -821,7 +820,7 @@ def _check_no_units(vals, names): raise ValueError(f"{name} must be a single scalar value, " f"but got {val}") - @docstring.dedent_interpd + @_docstring.dedent_interpd def axline(self, xy1, xy2=None, *, slope=None, **kwargs): """ Add an infinitely long straight line. @@ -895,7 +894,7 @@ def axline(self, xy1, xy2=None, *, slope=None, **kwargs): self._request_autoscale_view() return line - @docstring.dedent_interpd + @_docstring.dedent_interpd def axhspan(self, ymin, ymax, xmin=0, xmax=1, **kwargs): """ Add a horizontal span (rectangle) across the Axes. @@ -943,7 +942,7 @@ def axhspan(self, ymin, ymax, xmin=0, xmax=1, **kwargs): self._request_autoscale_view("y") return p - @docstring.dedent_interpd + @_docstring.dedent_interpd def axvspan(self, xmin, xmax, ymin=0, ymax=1, **kwargs): """ Add a vertical span (rectangle) across the Axes. @@ -1160,7 +1159,7 @@ def vlines(self, x, ymin, ymax, colors=None, linestyles='solid', @_preprocess_data(replace_names=["positions", "lineoffsets", "linelengths", "linewidths", "colors", "linestyles"]) - @docstring.dedent_interpd + @_docstring.dedent_interpd def eventplot(self, positions, orientation='horizontal', lineoffsets=1, linelengths=1, linewidths=None, colors=None, linestyles='solid', **kwargs): @@ -1392,7 +1391,7 @@ def eventplot(self, positions, orientation='horizontal', lineoffsets=1, # Uses a custom implementation of data-kwarg handling in # _process_plot_var_args. - @docstring.dedent_interpd + @_docstring.dedent_interpd def plot(self, *args, scalex=True, scaley=True, data=None, **kwargs): """ Plot y versus x as lines and/or markers. @@ -1646,7 +1645,7 @@ def plot(self, *args, scalex=True, scaley=True, data=None, **kwargs): return lines @_preprocess_data(replace_names=["x", "y"], label_namer="y") - @docstring.dedent_interpd + @_docstring.dedent_interpd def plot_date(self, x, y, fmt='o', tz=None, xdate=True, ydate=False, **kwargs): """ @@ -1727,7 +1726,7 @@ def plot_date(self, x, y, fmt='o', tz=None, xdate=True, ydate=False, return self.plot(x, y, fmt, **kwargs) # @_preprocess_data() # let 'plot' do the unpacking.. - @docstring.dedent_interpd + @_docstring.dedent_interpd def loglog(self, *args, **kwargs): """ Make a plot with log scaling on both the x and y axis. @@ -1781,7 +1780,7 @@ def loglog(self, *args, **kwargs): *args, **{k: v for k, v in kwargs.items() if k not in {*dx, *dy}}) # @_preprocess_data() # let 'plot' do the unpacking.. - @docstring.dedent_interpd + @_docstring.dedent_interpd def semilogx(self, *args, **kwargs): """ Make a plot with log scaling on the x axis. @@ -1828,7 +1827,7 @@ def semilogx(self, *args, **kwargs): *args, **{k: v for k, v in kwargs.items() if k not in d}) # @_preprocess_data() # let 'plot' do the unpacking.. - @docstring.dedent_interpd + @_docstring.dedent_interpd def semilogy(self, *args, **kwargs): """ Make a plot with log scaling on the y axis. @@ -2179,7 +2178,7 @@ def _convert_dx(dx, x0, xconv, convert): return dx @_preprocess_data() - @docstring.dedent_interpd + @_docstring.dedent_interpd def bar(self, x, height, width=0.8, bottom=None, *, align="center", **kwargs): r""" @@ -2456,7 +2455,7 @@ def bar(self, x, height, width=0.8, bottom=None, *, align="center", return bar_container - @docstring.dedent_interpd + @_docstring.dedent_interpd def barh(self, y, width, height=0.8, left=None, *, align="center", **kwargs): r""" @@ -2690,7 +2689,7 @@ def sign(x): return annotations @_preprocess_data() - @docstring.dedent_interpd + @_docstring.dedent_interpd def broken_barh(self, xranges, yrange, **kwargs): """ Plot a horizontal sequence of rectangles. @@ -3168,7 +3167,7 @@ def get_next_color(): @_preprocess_data(replace_names=["x", "y", "xerr", "yerr"], label_namer="y") - @docstring.dedent_interpd + @_docstring.dedent_interpd def errorbar(self, x, y, yerr=None, xerr=None, fmt='', ecolor=None, elinewidth=None, capsize=None, barsabove=False, lolims=False, uplims=False, @@ -4522,7 +4521,7 @@ def scatter(self, x, y, s=None, c=None, marker=None, cmap=None, norm=None, return collection @_preprocess_data(replace_names=["x", "y", "C"], label_namer="y") - @docstring.dedent_interpd + @_docstring.dedent_interpd def hexbin(self, x, y, C=None, gridsize=100, bins=None, xscale='linear', yscale='linear', extent=None, cmap=None, norm=None, vmin=None, vmax=None, @@ -4898,7 +4897,7 @@ def on_changed(collection): return collection - @docstring.dedent_interpd + @_docstring.dedent_interpd def arrow(self, x, y, dx, dy, **kwargs): """ Add an arrow to the Axes. @@ -4937,7 +4936,7 @@ def arrow(self, x, y, dx, dy, **kwargs): self._request_autoscale_view() return a - @docstring.copy(mquiver.QuiverKey.__init__) + @_docstring.copy(mquiver.QuiverKey.__init__) def quiverkey(self, Q, X, Y, U, label, **kwargs): qk = mquiver.QuiverKey(Q, X, Y, U, label, **kwargs) self.add_artist(qk) @@ -4953,7 +4952,7 @@ def _quiver_units(self, args, kwargs): # args can by a combination if X, Y, U, V, C and all should be replaced @_preprocess_data() - @docstring.dedent_interpd + @_docstring.dedent_interpd def quiver(self, *args, **kwargs): """%(quiver_doc)s""" # Make sure units are handled for x and y values @@ -4965,7 +4964,7 @@ def quiver(self, *args, **kwargs): # args can be some combination of X, Y, U, V, C and all should be replaced @_preprocess_data() - @docstring.dedent_interpd + @_docstring.dedent_interpd def barbs(self, *args, **kwargs): """%(barbs_doc)s""" # Make sure units are handled for x and y values @@ -5231,7 +5230,7 @@ def fill_between(self, x, y1, y2=0, where=None, interpolate=False, dir="horizontal", ind="x", dep="y" ) fill_between = _preprocess_data( - docstring.dedent_interpd(fill_between), + _docstring.dedent_interpd(fill_between), replace_names=["x", "y1", "y2", "where"]) def fill_betweenx(self, y, x1, x2=0, where=None, @@ -5245,7 +5244,7 @@ def fill_betweenx(self, y, x1, x2=0, where=None, dir="vertical", ind="y", dep="x" ) fill_betweenx = _preprocess_data( - docstring.dedent_interpd(fill_betweenx), + _docstring.dedent_interpd(fill_betweenx), replace_names=["y", "x1", "x2", "where"]) #### plotting z(x, y): imshow, pcolor and relatives, contour @@ -5602,7 +5601,7 @@ def _pcolor_grid_deprecation_helper(self): self.grid(False) @_preprocess_data() - @docstring.dedent_interpd + @_docstring.dedent_interpd def pcolor(self, *args, shading=None, alpha=None, norm=None, cmap=None, vmin=None, vmax=None, **kwargs): r""" @@ -5846,7 +5845,7 @@ def pcolor(self, *args, shading=None, alpha=None, norm=None, cmap=None, return collection @_preprocess_data() - @docstring.dedent_interpd + @_docstring.dedent_interpd def pcolormesh(self, *args, alpha=None, norm=None, cmap=None, vmin=None, vmax=None, shading=None, antialiased=False, **kwargs): """ @@ -6073,7 +6072,7 @@ def pcolormesh(self, *args, alpha=None, norm=None, cmap=None, vmin=None, return collection @_preprocess_data() - @docstring.dedent_interpd + @_docstring.dedent_interpd def pcolorfast(self, *args, alpha=None, norm=None, cmap=None, vmin=None, vmax=None, **kwargs): """ @@ -6263,7 +6262,7 @@ def pcolorfast(self, *args, alpha=None, norm=None, cmap=None, vmin=None, return ret @_preprocess_data() - @docstring.dedent_interpd + @_docstring.dedent_interpd def contour(self, *args, **kwargs): """ Plot contour lines. @@ -6279,7 +6278,7 @@ def contour(self, *args, **kwargs): return contours @_preprocess_data() - @docstring.dedent_interpd + @_docstring.dedent_interpd def contourf(self, *args, **kwargs): """ Plot filled contours. @@ -6856,7 +6855,7 @@ def stairs(self, values, edges=None, *, return patch @_preprocess_data(replace_names=["x", "y", "weights"]) - @docstring.dedent_interpd + @_docstring.dedent_interpd def hist2d(self, x, y, bins=10, range=None, density=False, weights=None, cmin=None, cmax=None, **kwargs): """ @@ -6968,7 +6967,7 @@ def hist2d(self, x, y, bins=10, range=None, density=False, weights=None, return h, xedges, yedges, pc @_preprocess_data(replace_names=["x"]) - @docstring.dedent_interpd + @_docstring.dedent_interpd def psd(self, x, NFFT=None, Fs=None, Fc=None, detrend=None, window=None, noverlap=None, pad_to=None, sides=None, scale_by_freq=None, return_line=None, **kwargs): @@ -7079,7 +7078,7 @@ def psd(self, x, NFFT=None, Fs=None, Fc=None, detrend=None, return pxx, freqs, line @_preprocess_data(replace_names=["x", "y"], label_namer="y") - @docstring.dedent_interpd + @_docstring.dedent_interpd def csd(self, x, y, NFFT=None, Fs=None, Fc=None, detrend=None, window=None, noverlap=None, pad_to=None, sides=None, scale_by_freq=None, return_line=None, **kwargs): @@ -7181,7 +7180,7 @@ def csd(self, x, y, NFFT=None, Fs=None, Fc=None, detrend=None, return pxy, freqs, line @_preprocess_data(replace_names=["x"]) - @docstring.dedent_interpd + @_docstring.dedent_interpd def magnitude_spectrum(self, x, Fs=None, Fc=None, window=None, pad_to=None, sides=None, scale=None, **kwargs): @@ -7267,7 +7266,7 @@ def magnitude_spectrum(self, x, Fs=None, Fc=None, window=None, return spec, freqs, line @_preprocess_data(replace_names=["x"]) - @docstring.dedent_interpd + @_docstring.dedent_interpd def angle_spectrum(self, x, Fs=None, Fc=None, window=None, pad_to=None, sides=None, **kwargs): """ @@ -7336,7 +7335,7 @@ def angle_spectrum(self, x, Fs=None, Fc=None, window=None, return spec, freqs, lines[0] @_preprocess_data(replace_names=["x"]) - @docstring.dedent_interpd + @_docstring.dedent_interpd def phase_spectrum(self, x, Fs=None, Fc=None, window=None, pad_to=None, sides=None, **kwargs): """ @@ -7405,7 +7404,7 @@ def phase_spectrum(self, x, Fs=None, Fc=None, window=None, return spec, freqs, lines[0] @_preprocess_data(replace_names=["x", "y"]) - @docstring.dedent_interpd + @_docstring.dedent_interpd def cohere(self, x, y, NFFT=256, Fs=2, Fc=0, detrend=mlab.detrend_none, window=mlab.window_hanning, noverlap=0, pad_to=None, sides='default', scale_by_freq=None, **kwargs): @@ -7470,7 +7469,7 @@ def cohere(self, x, y, NFFT=256, Fs=2, Fc=0, detrend=mlab.detrend_none, return cxy, freqs @_preprocess_data(replace_names=["x"]) - @docstring.dedent_interpd + @_docstring.dedent_interpd def specgram(self, x, NFFT=None, Fs=None, Fc=None, detrend=None, window=None, noverlap=None, cmap=None, xextent=None, pad_to=None, sides=None, @@ -7626,7 +7625,7 @@ def specgram(self, x, NFFT=None, Fs=None, Fc=None, detrend=None, return spec, freqs, t, im - @docstring.dedent_interpd + @_docstring.dedent_interpd def spy(self, Z, precision=0, marker=None, markersize=None, aspect='equal', origin="upper", **kwargs): """ diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index 44dfe1b1a202..3be469189a3b 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -12,7 +12,7 @@ import numpy as np import matplotlib as mpl -from matplotlib import _api, cbook, docstring, offsetbox +from matplotlib import _api, cbook, _docstring, offsetbox import matplotlib.artist as martist import matplotlib.axis as maxis from matplotlib.cbook import _OrderedSet, _check_1d, index_of @@ -3182,7 +3182,7 @@ def set_axisbelow(self, b): axis.set_zorder(zorder) self.stale = True - @docstring.dedent_interpd + @_docstring.dedent_interpd @_api.rename_parameter("3.5", "b", "visible") def grid(self, visible=None, which='major', axis='both', **kwargs): """ diff --git a/lib/matplotlib/axes/_secondary_axes.py b/lib/matplotlib/axes/_secondary_axes.py index f6248457d1da..55aeafa391b3 100644 --- a/lib/matplotlib/axes/_secondary_axes.py +++ b/lib/matplotlib/axes/_secondary_axes.py @@ -1,7 +1,6 @@ import numpy as np -from matplotlib import _api -import matplotlib.docstring as docstring +from matplotlib import _api, _docstring import matplotlib.ticker as mticker from matplotlib.axes._base import _AxesBase, _TransformedBoundsLocator from matplotlib.axis import Axis @@ -124,7 +123,7 @@ def apply_aspect(self, position=None): self._set_lims() super().apply_aspect(position) - @docstring.copy(Axis.set_ticks) + @_docstring.copy(Axis.set_ticks) def set_ticks(self, ticks, labels=None, *, minor=False, **kwargs): ret = self._axis.set_ticks(ticks, labels, minor=minor, **kwargs) self.stale = True @@ -294,4 +293,4 @@ def set_color(self, color): **kwargs : `~matplotlib.axes.Axes` properties. Other miscellaneous axes parameters. ''' -docstring.interpd.update(_secax_docstring=_secax_docstring) +_docstring.interpd.update(_secax_docstring=_secax_docstring) diff --git a/lib/matplotlib/backend_bases.py b/lib/matplotlib/backend_bases.py index 7fb3f8844616..0e7ee91a0a8c 100644 --- a/lib/matplotlib/backend_bases.py +++ b/lib/matplotlib/backend_bases.py @@ -43,7 +43,7 @@ import matplotlib as mpl from matplotlib import ( - _api, backend_tools as tools, cbook, colors, docstring, textpath, + _api, backend_tools as tools, cbook, colors, _docstring, textpath, _tight_bbox, transforms, widgets, get_backend, is_interactive, rcParams) from matplotlib._pylab_helpers import Gcf from matplotlib.backend_managers import ToolManager @@ -881,7 +881,7 @@ def set_antialiased(self, b): # Use ints to make life easier on extension code trying to read the gc. self._antialiased = int(bool(b)) - @docstring.interpd + @_docstring.interpd def set_capstyle(self, cs): """ Set how to draw endpoints of lines. @@ -949,7 +949,7 @@ def set_foreground(self, fg, isRGBA=False): else: self._rgb = colors.to_rgba(fg) - @docstring.interpd + @_docstring.interpd def set_joinstyle(self, js): """ Set how to draw connections between line segments. diff --git a/lib/matplotlib/collections.py b/lib/matplotlib/collections.py index 86c08c7177e7..d0df32638be8 100644 --- a/lib/matplotlib/collections.py +++ b/lib/matplotlib/collections.py @@ -17,7 +17,7 @@ import numpy as np import matplotlib as mpl -from . import (_api, _path, artist, cbook, cm, colors as mcolors, docstring, +from . import (_api, _path, artist, cbook, cm, colors as mcolors, _docstring, hatch as mhatch, lines as mlines, path as mpath, transforms) from ._enums import JoinStyle, CapStyle @@ -75,7 +75,7 @@ class Collection(artist.Artist, cm.ScalarMappable): # subclass-by-subclass basis. _edge_default = False - @docstring.interpd + @_docstring.interpd def __init__(self, edgecolors=None, facecolors=None, @@ -630,7 +630,7 @@ def set_linestyle(self, ls): self._linewidths, self._linestyles = self._bcast_lwls( self._us_lw, self._us_linestyles) - @docstring.interpd + @_docstring.interpd def set_capstyle(self, cs): """ Set the `.CapStyle` for the collection (for all its elements). @@ -644,7 +644,7 @@ def set_capstyle(self, cs): def get_capstyle(self): return self._capstyle.name - @docstring.interpd + @_docstring.interpd def set_joinstyle(self, js): """ Set the `.JoinStyle` for the collection (for all its elements). diff --git a/lib/matplotlib/colorbar.py b/lib/matplotlib/colorbar.py index 7093a83406d1..89c86981d3ff 100644 --- a/lib/matplotlib/colorbar.py +++ b/lib/matplotlib/colorbar.py @@ -24,7 +24,7 @@ import matplotlib.scale as mscale import matplotlib.spines as mspines import matplotlib.transforms as mtransforms -from matplotlib import docstring +from matplotlib import _docstring _log = logging.getLogger(__name__) @@ -117,7 +117,7 @@ unusual circumstances. """ -docstring.interpd.update(colorbar_doc=""" +_docstring.interpd.update(colorbar_doc=""" Add a colorbar to a plot. Parameters @@ -268,7 +268,7 @@ def get_subplotspec(self): return ss() -@docstring.Substitution(_colormap_kw_doc) +@_docstring.Substitution(_colormap_kw_doc) class Colorbar: r""" Draw a colorbar in an existing axes. @@ -1426,7 +1426,7 @@ def _normalize_location_orientation(location, orientation): return loc_settings -@docstring.Substitution(_make_axes_kw_doc) +@_docstring.Substitution(_make_axes_kw_doc) def make_axes(parents, location=None, orientation=None, fraction=0.15, shrink=1.0, aspect=20, **kwargs): """ @@ -1528,7 +1528,7 @@ def make_axes(parents, location=None, orientation=None, fraction=0.15, return cax, kwargs -@docstring.Substitution(_make_axes_kw_doc) +@_docstring.Substitution(_make_axes_kw_doc) def make_axes_gridspec(parent, *, location=None, orientation=None, fraction=0.15, shrink=1.0, aspect=20, **kwargs): """ diff --git a/lib/matplotlib/contour.py b/lib/matplotlib/contour.py index 225b2b43b83b..c467884c67ab 100644 --- a/lib/matplotlib/contour.py +++ b/lib/matplotlib/contour.py @@ -9,7 +9,7 @@ from numpy import ma import matplotlib as mpl -from matplotlib import _api, docstring +from matplotlib import _api, _docstring from matplotlib.backend_bases import MouseButton import matplotlib.path as mpath import matplotlib.ticker as ticker @@ -656,7 +656,7 @@ def _find_closest_point_on_path(xys, p): return (d2s[imin], projs[imin], (imin, imin+1)) -docstring.interpd.update(contour_set_attributes=r""" +_docstring.interpd.update(contour_set_attributes=r""" Attributes ---------- ax : `~matplotlib.axes.Axes` @@ -675,7 +675,7 @@ def _find_closest_point_on_path(xys, p): """) -@docstring.dedent_interpd +@_docstring.dedent_interpd class ContourSet(cm.ScalarMappable, ContourLabeler): """ Store a set of contour lines or filled regions. @@ -1404,7 +1404,7 @@ def find_nearest_contour(self, x, y, indices=None, pixel=True): return (conmin, segmin, imin, xmin, ymin, d2min) -@docstring.dedent_interpd +@_docstring.dedent_interpd class QuadContourSet(ContourSet): """ Create and store a set of contour lines or filled regions. @@ -1575,7 +1575,7 @@ def _initialize_x_y(self, z): return np.meshgrid(x, y) -docstring.interpd.update(contour_doc=""" +_docstring.interpd.update(contour_doc=""" `.contour` and `.contourf` draw contour lines and filled contours, respectively. Except as noted, function signatures and return values are the same for both versions. diff --git a/lib/matplotlib/docstring.py b/lib/matplotlib/docstring.py index 1beb6a17eb2a..b6ddcf5acd10 100644 --- a/lib/matplotlib/docstring.py +++ b/lib/matplotlib/docstring.py @@ -1,97 +1,4 @@ -import inspect - -from . import _api - - -class Substitution: - """ - A decorator that performs %-substitution on an object's docstring. - - This decorator should be robust even if ``obj.__doc__`` is None (for - example, if -OO was passed to the interpreter). - - Usage: construct a docstring.Substitution with a sequence or dictionary - suitable for performing substitution; then decorate a suitable function - with the constructed object, e.g.:: - - sub_author_name = Substitution(author='Jason') - - @sub_author_name - def some_function(x): - "%(author)s wrote this function" - - # note that some_function.__doc__ is now "Jason wrote this function" - - One can also use positional arguments:: - - sub_first_last_names = Substitution('Edgar Allen', 'Poe') - - @sub_first_last_names - def some_function(x): - "%s %s wrote the Raven" - """ - def __init__(self, *args, **kwargs): - if args and kwargs: - raise TypeError("Only positional or keyword args are allowed") - self.params = params = args or kwargs - - def __call__(self, func): - if func.__doc__: - func.__doc__ = inspect.cleandoc(func.__doc__) % self.params - return func - - def update(self, *args, **kwargs): - """ - Update ``self.params`` (which must be a dict) with the supplied args. - """ - self.params.update(*args, **kwargs) - - -class _ArtistKwdocLoader(dict): - def __missing__(self, key): - if not key.endswith(":kwdoc"): - raise KeyError(key) - name = key[:-len(":kwdoc")] - from matplotlib.artist import Artist, kwdoc - try: - cls, = [cls for cls in _api.recursive_subclasses(Artist) - if cls.__name__ == name] - except ValueError as e: - raise KeyError(key) from e - return self.setdefault(key, kwdoc(cls)) - - -class _ArtistPropertiesSubstitution(Substitution): - """ - A `.Substitution` with two additional features: - - - Substitutions of the form ``%(classname:kwdoc)s`` (ending with the - literal ":kwdoc" suffix) trigger lookup of an Artist subclass with the - given *classname*, and are substituted with the `.kwdoc` of that class. - - Decorating a class triggers substitution both on the class docstring and - on the class' ``__init__`` docstring (which is a commonly required - pattern for Artist subclasses). - """ - - def __init__(self): - self.params = _ArtistKwdocLoader() - - def __call__(self, obj): - super().__call__(obj) - if isinstance(obj, type) and obj.__init__ != object.__init__: - self(obj.__init__) - return obj - - -def copy(source): - """Copy a docstring from another source function (if present).""" - def do_copy(target): - if source.__doc__: - target.__doc__ = source.__doc__ - return target - return do_copy - - -# Create a decorator that will house the various docstring snippets reused -# throughout Matplotlib. -dedent_interpd = interpd = _ArtistPropertiesSubstitution() +from matplotlib._docstring import * # noqa: F401, F403 +from matplotlib import _api +_api.warn_deprecated( + "3.6", obj_type='module', name=f"{__name__}") diff --git a/lib/matplotlib/figure.py b/lib/matplotlib/figure.py index ea9cc2245429..974e46d6e4b3 100644 --- a/lib/matplotlib/figure.py +++ b/lib/matplotlib/figure.py @@ -23,7 +23,7 @@ import numpy as np import matplotlib as mpl -from matplotlib import _blocking_input, docstring, projections +from matplotlib import _blocking_input, _docstring, projections from matplotlib.artist import ( Artist, allow_rasterization, _finalize_rasterization) from matplotlib.backend_bases import ( @@ -377,27 +377,27 @@ def _suplabels(self, t, info, **kwargs): self.stale = True return suplab - @docstring.Substitution(x0=0.5, y0=0.98, name='suptitle', ha='center', - va='top') - @docstring.copy(_suplabels) + @_docstring.Substitution(x0=0.5, y0=0.98, name='suptitle', ha='center', + va='top') + @_docstring.copy(_suplabels) def suptitle(self, t, **kwargs): # docstring from _suplabels... info = {'name': '_suptitle', 'x0': 0.5, 'y0': 0.98, 'ha': 'center', 'va': 'top', 'rotation': 0} return self._suplabels(t, info, **kwargs) - @docstring.Substitution(x0=0.5, y0=0.01, name='supxlabel', ha='center', - va='bottom') - @docstring.copy(_suplabels) + @_docstring.Substitution(x0=0.5, y0=0.01, name='supxlabel', ha='center', + va='bottom') + @_docstring.copy(_suplabels) def supxlabel(self, t, **kwargs): # docstring from _suplabels... info = {'name': '_supxlabel', 'x0': 0.5, 'y0': 0.01, 'ha': 'center', 'va': 'bottom', 'rotation': 0} return self._suplabels(t, info, **kwargs) - @docstring.Substitution(x0=0.02, y0=0.5, name='supylabel', ha='left', - va='center') - @docstring.copy(_suplabels) + @_docstring.Substitution(x0=0.02, y0=0.5, name='supylabel', ha='left', + va='center') + @_docstring.copy(_suplabels) def supylabel(self, t, **kwargs): # docstring from _suplabels... info = {'name': '_supylabel', 'x0': 0.02, 'y0': 0.5, @@ -507,7 +507,7 @@ def add_artist(self, artist, clip=False): self.stale = True return artist - @docstring.dedent_interpd + @_docstring.dedent_interpd def add_axes(self, *args, **kwargs): """ Add an Axes to the figure. @@ -620,7 +620,7 @@ def add_axes(self, *args, **kwargs): key = (projection_class, pkw) return self._add_axes_internal(a, key) - @docstring.dedent_interpd + @_docstring.dedent_interpd def add_subplot(self, *args, **kwargs): """ Add an `~.axes.Axes` to the figure as part of a subplot arrangement. @@ -917,7 +917,7 @@ def _break_share_link(ax, grouper): # calls to legend() allow replacing it with figlegend() to generate the # docstring of pyplot.figlegend. - @docstring.dedent_interpd + @_docstring.dedent_interpd def legend(self, *args, **kwargs): """ Place a legend on the figure. @@ -1052,7 +1052,7 @@ def legend(self, *args, **kwargs): self.stale = True return l - @docstring.dedent_interpd + @_docstring.dedent_interpd def text(self, x, y, s, fontdict=None, **kwargs): """ Add text to figure. @@ -1102,7 +1102,7 @@ def text(self, x, y, s, fontdict=None, **kwargs): self.stale = True return text - @docstring.dedent_interpd + @_docstring.dedent_interpd def colorbar( self, mappable, cax=None, ax=None, use_gridspec=True, **kwargs): """%(colorbar_doc)s""" @@ -1458,7 +1458,7 @@ def sca(self, a): self._axobservers.process("_axes_change_event", self) return a - @docstring.dedent_interpd + @_docstring.dedent_interpd def gca(self, **kwargs): """ Get the current Axes. @@ -1907,7 +1907,7 @@ def _set_artist_props(self, a): a.set_transform(self.transSubfigure) -@docstring.interpd +@_docstring.interpd class SubFigure(FigureBase): """ Logical figure that can be placed inside a figure. @@ -2098,7 +2098,7 @@ def draw(self, renderer): self.stale = False -@docstring.interpd +@_docstring.interpd class Figure(FigureBase): """ The top level container for all the plot elements. diff --git a/lib/matplotlib/legend.py b/lib/matplotlib/legend.py index de0f48dff429..6615474ea84c 100644 --- a/lib/matplotlib/legend.py +++ b/lib/matplotlib/legend.py @@ -28,7 +28,7 @@ import numpy as np import matplotlib as mpl -from matplotlib import _api, docstring, colors, offsetbox +from matplotlib import _api, _docstring, colors, offsetbox from matplotlib.artist import Artist, allow_rasterization from matplotlib.cbook import silent_list from matplotlib.font_manager import FontProperties @@ -94,7 +94,7 @@ def _update_bbox_to_anchor(self, loc_in_canvas): self.legend.set_bbox_to_anchor(loc_in_bbox) -docstring.interpd.update(_legend_kw_doc=""" +_docstring.interpd.update(_legend_kw_doc=""" loc : str or pair of floats, default: :rc:`legend.loc` ('best' for axes, \ 'upper right' for figures) The location of the legend. @@ -294,7 +294,7 @@ class Legend(Artist): def __str__(self): return "Legend" - @docstring.dedent_interpd + @_docstring.dedent_interpd def __init__( self, parent, handles, labels, loc=None, diff --git a/lib/matplotlib/lines.py b/lib/matplotlib/lines.py index c4739e7de826..142ad185728e 100644 --- a/lib/matplotlib/lines.py +++ b/lib/matplotlib/lines.py @@ -9,8 +9,7 @@ import numpy as np -import matplotlib as mpl -from . import _api, artist, cbook, colors as mcolors, docstring, rcParams +from . import _api, cbook, colors as mcolors, _docstring, rcParams from .artist import Artist, allow_rasterization from .cbook import ( _to_unmasked_float_array, ls_mapper, ls_mapper_r, STEP_LOOKUP_MAP) @@ -197,7 +196,7 @@ def _slice_or_none(in_v, slc): raise ValueError(f"markevery={markevery!r} is not a recognized value") -@docstring.interpd +@_docstring.interpd @_api.define_aliases({ "antialiased": ["aa"], "color": ["c"], @@ -1123,7 +1122,7 @@ def set_linestyle(self, ls): *self._unscaled_dash_pattern, self._linewidth) self.stale = True - @docstring.interpd + @_docstring.interpd def set_marker(self, marker): """ Set the line marker. @@ -1277,7 +1276,7 @@ def update_from(self, other): self._marker = MarkerStyle(marker=other._marker) self._drawstyle = other._drawstyle - @docstring.interpd + @_docstring.interpd def set_dash_joinstyle(self, s): """ How to join segments of the line if it `~Line2D.is_dashed`. @@ -1293,7 +1292,7 @@ def set_dash_joinstyle(self, s): self.stale = True self._dashjoinstyle = js - @docstring.interpd + @_docstring.interpd def set_solid_joinstyle(self, s): """ How to join segments if the line is solid (not `~Line2D.is_dashed`). @@ -1325,7 +1324,7 @@ def get_solid_joinstyle(self): """ return self._solidjoinstyle.name - @docstring.interpd + @_docstring.interpd def set_dash_capstyle(self, s): """ How to draw the end caps if the line is `~Line2D.is_dashed`. @@ -1341,7 +1340,7 @@ def set_dash_capstyle(self, s): self.stale = True self._dashcapstyle = cs - @docstring.interpd + @_docstring.interpd def set_solid_capstyle(self, s): """ How to draw the end caps if the line is solid (not `~Line2D.is_dashed`) diff --git a/lib/matplotlib/markers.py b/lib/matplotlib/markers.py index d0f55fc037f0..65f97ec6989e 100644 --- a/lib/matplotlib/markers.py +++ b/lib/matplotlib/markers.py @@ -527,7 +527,7 @@ def _set_mathtext_path(self): Submitted by tcb """ - from matplotlib.text import TextPath + from matplotlib.textpath import TextPath # again, the properties could be initialised just once outside # this function diff --git a/lib/matplotlib/mlab.py b/lib/matplotlib/mlab.py index 60936c7d0a37..f30ed22433cc 100644 --- a/lib/matplotlib/mlab.py +++ b/lib/matplotlib/mlab.py @@ -55,9 +55,7 @@ import numpy as np -from matplotlib import _api -import matplotlib.cbook as cbook -from matplotlib import docstring +from matplotlib import _api, _docstring, cbook def window_hanning(x): @@ -475,7 +473,7 @@ def _single_spectrum_helper( # Split out these keyword docs so that they can be used elsewhere -docstring.interpd.update( +_docstring.interpd.update( Spectral="""\ Fs : float, default: 2 The sampling frequency (samples per time unit). It is used to calculate @@ -533,7 +531,7 @@ def _single_spectrum_helper( MATLAB compatibility.""") -@docstring.dedent_interpd +@_docstring.dedent_interpd def psd(x, NFFT=None, Fs=None, detrend=None, window=None, noverlap=None, pad_to=None, sides=None, scale_by_freq=None): r""" @@ -589,7 +587,7 @@ def psd(x, NFFT=None, Fs=None, detrend=None, window=None, return Pxx.real, freqs -@docstring.dedent_interpd +@_docstring.dedent_interpd def csd(x, y, NFFT=None, Fs=None, detrend=None, window=None, noverlap=None, pad_to=None, sides=None, scale_by_freq=None): """ @@ -694,22 +692,22 @@ def csd(x, y, NFFT=None, Fs=None, detrend=None, window=None, complex_spectrum = functools.partial(_single_spectrum_helper, "complex") complex_spectrum.__doc__ = _single_spectrum_docs.format( quantity="complex-valued frequency spectrum", - **docstring.interpd.params) + **_docstring.interpd.params) magnitude_spectrum = functools.partial(_single_spectrum_helper, "magnitude") magnitude_spectrum.__doc__ = _single_spectrum_docs.format( quantity="magnitude (absolute value) of the frequency spectrum", - **docstring.interpd.params) + **_docstring.interpd.params) angle_spectrum = functools.partial(_single_spectrum_helper, "angle") angle_spectrum.__doc__ = _single_spectrum_docs.format( quantity="angle of the frequency spectrum (wrapped phase spectrum)", - **docstring.interpd.params) + **_docstring.interpd.params) phase_spectrum = functools.partial(_single_spectrum_helper, "phase") phase_spectrum.__doc__ = _single_spectrum_docs.format( quantity="phase of the frequency spectrum (unwrapped phase spectrum)", - **docstring.interpd.params) + **_docstring.interpd.params) -@docstring.dedent_interpd +@_docstring.dedent_interpd def specgram(x, NFFT=None, Fs=None, detrend=None, window=None, noverlap=None, pad_to=None, sides=None, scale_by_freq=None, mode=None): @@ -792,7 +790,7 @@ def specgram(x, NFFT=None, Fs=None, detrend=None, window=None, return spec, freqs, t -@docstring.dedent_interpd +@_docstring.dedent_interpd def cohere(x, y, NFFT=256, Fs=2, detrend=detrend_none, window=window_hanning, noverlap=0, pad_to=None, sides='default', scale_by_freq=None): r""" diff --git a/lib/matplotlib/offsetbox.py b/lib/matplotlib/offsetbox.py index f4f5e1561f15..1a18ffdc4831 100644 --- a/lib/matplotlib/offsetbox.py +++ b/lib/matplotlib/offsetbox.py @@ -24,7 +24,7 @@ import numpy as np -from matplotlib import _api, docstring, rcParams +from matplotlib import _api, _docstring, rcParams import matplotlib.artist as martist import matplotlib.path as mpath import matplotlib.text as mtext @@ -1278,7 +1278,7 @@ class AnnotationBbox(martist.Artist, mtext._AnnotationBase): def __str__(self): return "AnnotationBbox(%g,%g)" % (self.xy[0], self.xy[1]) - @docstring.dedent_interpd + @_docstring.dedent_interpd def __init__(self, offsetbox, xy, xybox=None, xycoords='data', diff --git a/lib/matplotlib/patches.py b/lib/matplotlib/patches.py index f5d84281c64c..fd81dbb591c1 100644 --- a/lib/matplotlib/patches.py +++ b/lib/matplotlib/patches.py @@ -13,7 +13,7 @@ import numpy as np import matplotlib as mpl -from . import (_api, artist, cbook, colors, docstring, hatch as mhatch, +from . import (_api, artist, cbook, colors, _docstring, hatch as mhatch, lines as mlines, transforms) from .bezier import ( NonIntersectingPathException, get_cos_sin, get_intersection, @@ -23,7 +23,7 @@ from ._enums import JoinStyle, CapStyle -@docstring.interpd +@_docstring.interpd @_api.define_aliases({ "antialiased": ["aa"], "edgecolor": ["ec"], @@ -451,7 +451,7 @@ def get_fill(self): # attribute. fill = property(get_fill, set_fill) - @docstring.interpd + @_docstring.interpd def set_capstyle(self, s): """ Set the `.CapStyle`. @@ -471,7 +471,7 @@ def get_capstyle(self): """Return the capstyle.""" return self._capstyle.name - @docstring.interpd + @_docstring.interpd def set_joinstyle(self, s): """ Set the `.JoinStyle`. @@ -617,7 +617,7 @@ class Shadow(Patch): def __str__(self): return "Shadow(%s)" % (str(self.patch)) - @docstring.dedent_interpd + @_docstring.dedent_interpd def __init__(self, patch, ox, oy, **kwargs): """ Create a shadow of the given *patch*. @@ -689,7 +689,7 @@ def __str__(self): fmt = "Rectangle(xy=(%g, %g), width=%g, height=%g, angle=%g)" return fmt % pars - @docstring.dedent_interpd + @_docstring.dedent_interpd def __init__(self, xy, width, height, angle=0.0, *, rotation_point='xy', **kwargs): """ @@ -891,7 +891,7 @@ def __str__(self): return s % (self.xy[0], self.xy[1], self.numvertices, self.radius, self.orientation) - @docstring.dedent_interpd + @_docstring.dedent_interpd def __init__(self, xy, numVertices, radius=5, orientation=0, **kwargs): """ @@ -941,7 +941,7 @@ def __str__(self): s = "PathPatch%d((%g, %g) ...)" return s % (len(self._path.vertices), *tuple(self._path.vertices[0])) - @docstring.dedent_interpd + @_docstring.dedent_interpd def __init__(self, path, **kwargs): """ *path* is a `~.path.Path` object. @@ -970,7 +970,7 @@ class StepPatch(PathPatch): _edge_default = False - @docstring.dedent_interpd + @_docstring.dedent_interpd def __init__(self, values, edges, *, orientation='vertical', baseline=0, **kwargs): """ @@ -1078,7 +1078,7 @@ def __str__(self): else: return "Polygon0()" - @docstring.dedent_interpd + @_docstring.dedent_interpd def __init__(self, xy, closed=True, **kwargs): """ *xy* is a numpy array with shape Nx2. @@ -1174,7 +1174,7 @@ def __str__(self): fmt = "Wedge(center=(%g, %g), r=%g, theta1=%g, theta2=%g, width=%s)" return fmt % pars - @docstring.dedent_interpd + @_docstring.dedent_interpd def __init__(self, center, r, theta1, theta2, width=None, **kwargs): """ A wedge centered at *x*, *y* center with radius *r* that @@ -1270,7 +1270,7 @@ def __str__(self): [0.8, 0.1], [0.0, 0.1]], closed=True) - @docstring.dedent_interpd + @_docstring.dedent_interpd def __init__(self, x, y, dx, dy, width=1.0, **kwargs): """ Draws an arrow from (*x*, *y*) to (*x* + *dx*, *y* + *dy*). @@ -1325,7 +1325,7 @@ class FancyArrow(Polygon): def __str__(self): return "FancyArrow()" - @docstring.dedent_interpd + @_docstring.dedent_interpd def __init__(self, x, y, dx, dy, width=0.001, length_includes_head=False, head_width=None, head_length=None, shape='full', overhang=0, head_starts_at_zero=False, **kwargs): @@ -1483,7 +1483,7 @@ def _make_verts(self): ] -docstring.interpd.update( +_docstring.interpd.update( FancyArrow="\n".join( (inspect.getdoc(FancyArrow.__init__) or "").splitlines()[2:])) @@ -1495,7 +1495,7 @@ def __str__(self): s = "CirclePolygon((%g, %g), radius=%g, resolution=%d)" return s % (self.xy[0], self.xy[1], self.radius, self.numvertices) - @docstring.dedent_interpd + @_docstring.dedent_interpd def __init__(self, xy, radius=5, resolution=20, # the number of vertices ** kwargs): @@ -1521,7 +1521,7 @@ def __str__(self): fmt = "Ellipse(xy=(%s, %s), width=%s, height=%s, angle=%s)" return fmt % pars - @docstring.dedent_interpd + @_docstring.dedent_interpd def __init__(self, xy, width, height, angle=0, **kwargs): """ Parameters @@ -1669,7 +1669,7 @@ class Annulus(Patch): An elliptical annulus. """ - @docstring.dedent_interpd + @_docstring.dedent_interpd def __init__(self, xy, r, width, angle=0.0, **kwargs): """ Parameters @@ -1860,7 +1860,7 @@ def __str__(self): fmt = "Circle(xy=(%g, %g), radius=%g)" return fmt % pars - @docstring.dedent_interpd + @_docstring.dedent_interpd def __init__(self, xy, radius=5, **kwargs): """ Create a true circle at center *xy* = (*x*, *y*) with given *radius*. @@ -1912,7 +1912,7 @@ def __str__(self): "height=%g, angle=%g, theta1=%g, theta2=%g)") return fmt % pars - @docstring.dedent_interpd + @_docstring.dedent_interpd def __init__(self, xy, width, height, angle=0.0, theta1=0.0, theta2=360.0, **kwargs): """ @@ -3892,15 +3892,15 @@ def transmute(self, path, mutation_size, linewidth): return path, True -docstring.interpd.update( +_docstring.interpd.update( AvailableBoxstyles=BoxStyle.pprint_styles(), ListBoxstyles=_simpleprint_styles(BoxStyle._style_list), AvailableArrowstyles=ArrowStyle.pprint_styles(), AvailableConnectorstyles=ConnectionStyle.pprint_styles(), ) -docstring.dedent_interpd(BoxStyle) -docstring.dedent_interpd(ArrowStyle) -docstring.dedent_interpd(ConnectionStyle) +_docstring.dedent_interpd(BoxStyle) +_docstring.dedent_interpd(ArrowStyle) +_docstring.dedent_interpd(ConnectionStyle) class FancyBboxPatch(Patch): @@ -3919,7 +3919,7 @@ def __str__(self): s = self.__class__.__name__ + "((%g, %g), width=%g, height=%g)" return s % (self._x, self._y, self._width, self._height) - @docstring.dedent_interpd + @_docstring.dedent_interpd @_api.delete_parameter("3.4", "bbox_transmuter", alternative="boxstyle") def __init__(self, xy, width, height, boxstyle="round", bbox_transmuter=None, @@ -3989,7 +3989,7 @@ def __init__(self, xy, width, height, self.stale = True - @docstring.dedent_interpd + @_docstring.dedent_interpd def set_boxstyle(self, boxstyle=None, **kwargs): """ Set the box style. @@ -4210,7 +4210,7 @@ def __str__(self): else: return f"{type(self).__name__}({self._path_original})" - @docstring.dedent_interpd + @_docstring.dedent_interpd def __init__(self, posA=None, posB=None, path=None, arrowstyle="simple", connectionstyle="arc3", patchA=None, patchB=None, @@ -4525,7 +4525,7 @@ def __str__(self): return "ConnectionPatch((%g, %g), (%g, %g))" % \ (self.xy1[0], self.xy1[1], self.xy2[0], self.xy2[1]) - @docstring.dedent_interpd + @_docstring.dedent_interpd def __init__(self, xyA, xyB, coordsA, coordsB=None, axesA=None, axesB=None, arrowstyle="-", diff --git a/lib/matplotlib/projections/__init__.py b/lib/matplotlib/projections/__init__.py index 566492dc5368..16a5651da1d1 100644 --- a/lib/matplotlib/projections/__init__.py +++ b/lib/matplotlib/projections/__init__.py @@ -52,7 +52,7 @@ `matplotlib.projections.polar` may also be of interest. """ -from .. import axes, docstring +from .. import axes, _docstring from .geo import AitoffAxes, HammerAxes, LambertAxes, MollweideAxes from .polar import PolarAxes from mpl_toolkits.mplot3d import Axes3D @@ -111,4 +111,4 @@ def get_projection_class(projection=None): get_projection_names = projection_registry.get_projection_names -docstring.interpd.update(projection_names=get_projection_names()) +_docstring.interpd.update(projection_names=get_projection_names()) diff --git a/lib/matplotlib/pyplot.py b/lib/matplotlib/pyplot.py index 48131a5b1950..66885c2216b0 100644 --- a/lib/matplotlib/pyplot.py +++ b/lib/matplotlib/pyplot.py @@ -52,7 +52,7 @@ from matplotlib import rcsetup, style from matplotlib import _pylab_helpers, interactive from matplotlib import cbook -from matplotlib import docstring +from matplotlib import _docstring from matplotlib.backend_bases import FigureCanvasBase, MouseButton from matplotlib.figure import Figure, figaspect from matplotlib.gridspec import GridSpec, SubplotSpec @@ -88,7 +88,7 @@ def _copy_docstring_and_deprecators(method, func=None): if func is None: return functools.partial(_copy_docstring_and_deprecators, method) - decorators = [docstring.copy(method)] + decorators = [_docstring.copy(method)] # Check whether the definition of *method* includes @_api.rename_parameter # or @_api.make_keyword_only decorators; if so, propagate them to the # pyplot wrapper as well. @@ -990,7 +990,7 @@ def figlegend(*args, **kwargs): ## Axes ## -@docstring.dedent_interpd +@_docstring.dedent_interpd def axes(arg=None, **kwargs): """ Add an Axes to the current figure and make it the current Axes. @@ -1113,7 +1113,7 @@ def cla(): ## More ways of creating axes ## -@docstring.dedent_interpd +@_docstring.dedent_interpd def subplot(*args, **kwargs): """ Add an Axes to the current figure or retrieve an existing Axes. diff --git a/lib/matplotlib/quiver.py b/lib/matplotlib/quiver.py index 7f1b693aea82..7c3e5c74a490 100644 --- a/lib/matplotlib/quiver.py +++ b/lib/matplotlib/quiver.py @@ -20,7 +20,7 @@ import numpy as np from numpy import ma -from matplotlib import _api, cbook, docstring, font_manager +from matplotlib import _api, cbook, _docstring, font_manager import matplotlib.artist as martist import matplotlib.collections as mcollections from matplotlib.patches import CirclePolygon @@ -201,9 +201,9 @@ See Also -------- .Axes.quiverkey : Add a key to a quiver plot. -""" % docstring.interpd.params +""" % _docstring.interpd.params -docstring.interpd.update(quiver_doc=_quiver_doc) +_docstring.interpd.update(quiver_doc=_quiver_doc) class QuiverKey(martist.Artist): @@ -467,7 +467,7 @@ class Quiver(mcollections.PolyCollection): _PIVOT_VALS = ('tail', 'middle', 'tip') - @docstring.Substitution(_quiver_doc) + @_docstring.Substitution(_quiver_doc) def __init__(self, ax, *args, scale=None, headwidth=3, headlength=5, headaxislength=4.5, minshaft=1, minlength=1, units='width', scale_units=None, @@ -883,9 +883,9 @@ def _h_arrows(self, length): arguments: %(PolyCollection:kwdoc)s -""" % docstring.interpd.params +""" % _docstring.interpd.params -docstring.interpd.update(barbs_doc=_barbs_doc) +_docstring.interpd.update(barbs_doc=_barbs_doc) class Barbs(mcollections.PolyCollection): @@ -905,7 +905,7 @@ class Barbs(mcollections.PolyCollection): # This may be an abuse of polygons here to render what is essentially maybe # 1 triangle and a series of lines. It works fine as far as I can tell # however. - @docstring.interpd + @_docstring.interpd def __init__(self, ax, *args, pivot='tip', length=7, barbcolor=None, flagcolor=None, sizes=None, fill_empty=False, barb_increments=None, diff --git a/lib/matplotlib/sankey.py b/lib/matplotlib/sankey.py index 196df813a3a4..d04a040d1489 100644 --- a/lib/matplotlib/sankey.py +++ b/lib/matplotlib/sankey.py @@ -11,7 +11,7 @@ from matplotlib.path import Path from matplotlib.patches import PathPatch from matplotlib.transforms import Affine2D -from matplotlib import docstring +from matplotlib import _docstring _log = logging.getLogger(__name__) @@ -351,7 +351,7 @@ def _revert(self, path, first_action=Path.LINETO): # path[2] = path[2][::-1] # return path - @docstring.dedent_interpd + @_docstring.dedent_interpd def add(self, patchlabel='', flows=None, orientations=None, labels='', trunklength=1.0, pathlengths=0.25, prior=None, connect=(0, 0), rotation=0, **kwargs): diff --git a/lib/matplotlib/scale.py b/lib/matplotlib/scale.py index 51fe384f993e..a2d07fdfa1a5 100644 --- a/lib/matplotlib/scale.py +++ b/lib/matplotlib/scale.py @@ -18,7 +18,7 @@ import numpy as np import matplotlib as mpl -from matplotlib import _api, docstring +from matplotlib import _api, _docstring from matplotlib.ticker import ( NullFormatter, ScalarFormatter, LogFormatterSciNotation, LogitFormatter, NullLocator, LogLocator, AutoLocator, AutoMinorLocator, @@ -747,7 +747,7 @@ def _get_scale_docs(): return "\n".join(docs) -docstring.interpd.update( +_docstring.interpd.update( scale_type='{%s}' % ', '.join([repr(x) for x in get_scale_names()]), scale_docs=_get_scale_docs().rstrip(), ) diff --git a/lib/matplotlib/spines.py b/lib/matplotlib/spines.py index deb0a65d21f6..af8c60dece39 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, docstring, rcParams +from matplotlib import _api, _docstring, rcParams from matplotlib.artist import allow_rasterization import matplotlib.transforms as mtransforms import matplotlib.patches as mpatches @@ -31,7 +31,7 @@ class Spine(mpatches.Patch): def __str__(self): return "Spine" - @docstring.dedent_interpd + @_docstring.dedent_interpd def __init__(self, axes, spine_type, path, **kwargs): """ Parameters diff --git a/lib/matplotlib/style/core.py b/lib/matplotlib/style/core.py index b30f7627eca9..7bb96ed5b1bb 100644 --- a/lib/matplotlib/style/core.py +++ b/lib/matplotlib/style/core.py @@ -19,7 +19,7 @@ import warnings import matplotlib as mpl -from matplotlib import _api, docstring, rc_params_from_file, rcParamsDefault +from matplotlib import _api, _docstring, rc_params_from_file, rcParamsDefault _log = logging.getLogger(__name__) @@ -62,7 +62,7 @@ def _apply_style(d, warn=True): mpl.rcParams.update(_remove_blacklisted_style_params(d, warn=warn)) -@docstring.Substitution( +@_docstring.Substitution( "\n".join(map("- {}".format, sorted(STYLE_BLACKLIST, key=str.lower))) ) def use(style): diff --git a/lib/matplotlib/table.py b/lib/matplotlib/table.py index 086872e69088..b91b2a59ed03 100644 --- a/lib/matplotlib/table.py +++ b/lib/matplotlib/table.py @@ -24,7 +24,7 @@ Thanks to John Gill for providing the class and table. """ -from . import _api, docstring +from . import _api, _docstring from .artist import Artist, allow_rasterization from .patches import Rectangle from .text import Text @@ -175,7 +175,7 @@ def get_required_width(self, renderer): l, b, w, h = self.get_text_bounds(renderer) return w * (1.0 + (2.0 * self.PAD)) - @docstring.dedent_interpd + @_docstring.dedent_interpd def set_text_props(self, **kwargs): """ Update the text properties. @@ -644,7 +644,7 @@ def get_celld(self): return self._cells -@docstring.dedent_interpd +@_docstring.dedent_interpd def table(ax, cellText=None, cellColours=None, cellLoc='right', colWidths=None, diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index b2bc70ff6143..a5f5ddad93c4 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -6800,7 +6800,7 @@ def color_boxes(fig, ax): for nn, axx in enumerate([ax.xaxis, ax.yaxis]): bb = axx.get_tightbbox(renderer) if bb: - axisr = plt.Rectangle( + axisr = mpatches.Rectangle( (bb.x0, bb.y0), width=bb.width, height=bb.height, linewidth=0.7, edgecolor='y', facecolor="none", transform=None, zorder=3) @@ -6810,7 +6810,7 @@ def color_boxes(fig, ax): bbspines = [] for nn, a in enumerate(['bottom', 'top', 'left', 'right']): bb = ax.spines[a].get_window_extent(renderer) - spiner = plt.Rectangle( + spiner = mpatches.Rectangle( (bb.x0, bb.y0), width=bb.width, height=bb.height, linewidth=0.7, edgecolor="green", facecolor="none", transform=None, zorder=3) @@ -6818,7 +6818,7 @@ def color_boxes(fig, ax): bbspines += [bb] bb = ax.get_window_extent() - rect2 = plt.Rectangle( + rect2 = mpatches.Rectangle( (bb.x0, bb.y0), width=bb.width, height=bb.height, linewidth=1.5, edgecolor="magenta", facecolor="none", transform=None, zorder=2) @@ -6826,7 +6826,7 @@ def color_boxes(fig, ax): bbax = bb bb2 = ax.get_tightbbox(renderer) - rect2 = plt.Rectangle( + rect2 = mpatches.Rectangle( (bb2.x0, bb2.y0), width=bb2.width, height=bb2.height, linewidth=3, edgecolor="red", facecolor="none", transform=None, zorder=1) diff --git a/lib/matplotlib/tests/test_backend_pdf.py b/lib/matplotlib/tests/test_backend_pdf.py index 7d46f6bf3c1a..092fe0565c54 100644 --- a/lib/matplotlib/tests/test_backend_pdf.py +++ b/lib/matplotlib/tests/test_backend_pdf.py @@ -14,7 +14,7 @@ from matplotlib.ft2font import FT2Font from matplotlib.backends._backend_pdf_ps import get_glyphs_subset from matplotlib.backends.backend_pdf import PdfPages - +from matplotlib.patches import Rectangle from matplotlib.testing.decorators import check_figures_equal, image_comparison @@ -277,8 +277,8 @@ def test_hatching_legend(): """Test for correct hatching on patches in legend""" fig = plt.figure(figsize=(1, 2)) - a = plt.Rectangle([0, 0], 0, 0, facecolor="green", hatch="XXXX") - b = plt.Rectangle([0, 0], 0, 0, facecolor="blue", hatch="XXXX") + a = Rectangle([0, 0], 0, 0, facecolor="green", hatch="XXXX") + b = Rectangle([0, 0], 0, 0, facecolor="blue", hatch="XXXX") fig.legend([a, b, a, b], ["", "", "", ""]) diff --git a/lib/matplotlib/tests/test_backend_svg.py b/lib/matplotlib/tests/test_backend_svg.py index 6899f41301fb..84b56aea20fa 100644 --- a/lib/matplotlib/tests/test_backend_svg.py +++ b/lib/matplotlib/tests/test_backend_svg.py @@ -8,6 +8,7 @@ import matplotlib as mpl from matplotlib.figure import Figure +from matplotlib.text import Text import matplotlib.pyplot as plt from matplotlib.testing.decorators import image_comparison, check_figures_equal @@ -252,7 +253,7 @@ def include(gid, obj): # we need to exclude certain objects which will not appear in the svg if isinstance(obj, OffsetBox): return False - if isinstance(obj, plt.Text): + if isinstance(obj, Text): if obj.get_text() == "": return False elif obj.axes is None: diff --git a/lib/matplotlib/text.py b/lib/matplotlib/text.py index a664736b0902..a98b534d2ef6 100644 --- a/lib/matplotlib/text.py +++ b/lib/matplotlib/text.py @@ -11,7 +11,7 @@ import numpy as np import matplotlib as mpl -from . import _api, artist, cbook, docstring +from . import _api, artist, cbook, _docstring from .artist import Artist from .font_manager import FontProperties from .patches import FancyArrowPatch, FancyBboxPatch, Rectangle @@ -105,7 +105,7 @@ def _get_text_metrics_with_cache_impl( return renderer_ref().get_text_width_height_descent(text, fontprop, ismath) -@docstring.interpd +@_docstring.interpd @_api.define_aliases({ "color": ["c"], "fontfamily": ["family"], @@ -2015,4 +2015,4 @@ def get_tightbbox(self, renderer): return super().get_tightbbox(renderer) -docstring.interpd.update(Annotation=Annotation.__init__.__doc__) +_docstring.interpd.update(Annotation=Annotation.__init__.__doc__) diff --git a/lib/matplotlib/tri/tricontour.py b/lib/matplotlib/tri/tricontour.py index 069e1462a148..d2c1ada868b4 100644 --- a/lib/matplotlib/tri/tricontour.py +++ b/lib/matplotlib/tri/tricontour.py @@ -1,11 +1,11 @@ import numpy as np -from matplotlib import docstring +from matplotlib import _docstring from matplotlib.contour import ContourSet from matplotlib.tri.triangulation import Triangulation -@docstring.dedent_interpd +@_docstring.dedent_interpd class TriContourSet(ContourSet): """ Create and store a set of contour lines or filled regions for @@ -81,7 +81,7 @@ def _contour_args(self, args, kwargs): return (tri, z) -docstring.interpd.update(_tricontour_doc=""" +_docstring.interpd.update(_tricontour_doc=""" Draw contour %(type)s on an unstructured triangular grid. The triangulation can be specified in one of two ways; either :: @@ -252,8 +252,8 @@ def _contour_args(self, args, kwargs): it is taken from :rc:`lines.antialiased`.""") -@docstring.Substitution(func='tricontour', type='lines') -@docstring.dedent_interpd +@_docstring.Substitution(func='tricontour', type='lines') +@_docstring.dedent_interpd def tricontour(ax, *args, **kwargs): """ %(_tricontour_doc)s @@ -281,8 +281,8 @@ def tricontour(ax, *args, **kwargs): return TriContourSet(ax, *args, **kwargs) -@docstring.Substitution(func='tricontourf', type='regions') -@docstring.dedent_interpd +@_docstring.Substitution(func='tricontourf', type='regions') +@_docstring.dedent_interpd def tricontourf(ax, *args, **kwargs): """ %(_tricontour_doc)s diff --git a/lib/matplotlib/widgets.py b/lib/matplotlib/widgets.py index c545e113553d..bee2bd533a3a 100644 --- a/lib/matplotlib/widgets.py +++ b/lib/matplotlib/widgets.py @@ -16,8 +16,8 @@ import numpy as np import matplotlib as mpl -from matplotlib import docstring -from . import _api, backend_tools, cbook, colors, ticker, transforms +from . import (_api, _docstring, backend_tools, cbook, colors, ticker, + transforms) from .lines import Line2D from .patches import Circle, Rectangle, Ellipse from .transforms import TransformedPatchPath, Affine2D @@ -2844,7 +2844,7 @@ def onselect(eclick: MouseEvent, erelease: MouseEvent) """ -@docstring.Substitution(_RECTANGLESELECTOR_PARAMETERS_DOCSTRING.replace( +@_docstring.Substitution(_RECTANGLESELECTOR_PARAMETERS_DOCSTRING.replace( '__ARTIST_NAME__', 'rectangle')) class RectangleSelector(_SelectorWidget): """ @@ -3404,7 +3404,7 @@ def geometry(self): return np.array(self._selection_artist.get_data()) -@docstring.Substitution(_RECTANGLESELECTOR_PARAMETERS_DOCSTRING.replace( +@_docstring.Substitution(_RECTANGLESELECTOR_PARAMETERS_DOCSTRING.replace( '__ARTIST_NAME__', 'ellipse')) class EllipseSelector(RectangleSelector): """ diff --git a/lib/mpl_toolkits/axes_grid1/inset_locator.py b/lib/mpl_toolkits/axes_grid1/inset_locator.py index 638f90d15ff8..56e3b83573b1 100644 --- a/lib/mpl_toolkits/axes_grid1/inset_locator.py +++ b/lib/mpl_toolkits/axes_grid1/inset_locator.py @@ -2,7 +2,7 @@ A collection of functions and objects for creating or placing inset axes. """ -from matplotlib import _api, docstring +from matplotlib import _api, _docstring from matplotlib.offsetbox import AnchoredOffsetbox from matplotlib.patches import Patch, Rectangle from matplotlib.path import Path @@ -14,7 +14,7 @@ class InsetPosition: - @docstring.dedent_interpd + @_docstring.dedent_interpd def __init__(self, parent, lbwh): """ An object for positioning an inset axes. @@ -135,7 +135,7 @@ def get_extent(self, renderer): class BboxPatch(Patch): - @docstring.dedent_interpd + @_docstring.dedent_interpd def __init__(self, bbox, **kwargs): """ Patch showing the shape bounded by a Bbox. @@ -198,7 +198,7 @@ def connect_bbox(bbox1, bbox2, loc1, loc2=None): x2, y2 = BboxConnector.get_bbox_edge_pos(bbox2, loc2) return Path([[x1, y1], [x2, y2]]) - @docstring.dedent_interpd + @_docstring.dedent_interpd def __init__(self, bbox1, bbox2, loc1, loc2=None, **kwargs): """ Connect two bboxes with a straight line. @@ -244,7 +244,7 @@ def get_path(self): class BboxConnectorPatch(BboxConnector): - @docstring.dedent_interpd + @_docstring.dedent_interpd def __init__(self, bbox1, bbox2, loc1a, loc2a, loc1b, loc2b, **kwargs): """ Connect two bboxes with a quadrilateral. @@ -295,7 +295,7 @@ def _add_inset_axes(parent_axes, inset_axes): inset_axes.set_navigate(False) -@docstring.dedent_interpd +@_docstring.dedent_interpd def inset_axes(parent_axes, width, height, loc='upper right', bbox_to_anchor=None, bbox_transform=None, axes_class=None, axes_kwargs=None, @@ -435,7 +435,7 @@ def inset_axes(parent_axes, width, height, loc='upper right', return inset_axes -@docstring.dedent_interpd +@_docstring.dedent_interpd def zoomed_inset_axes(parent_axes, zoom, loc='upper right', bbox_to_anchor=None, bbox_transform=None, axes_class=None, axes_kwargs=None, @@ -538,7 +538,7 @@ def get_points(self): return super().get_points() -@docstring.dedent_interpd +@_docstring.dedent_interpd def mark_inset(parent_axes, inset_axes, loc1, loc2, **kwargs): """ Draw a box to mark the location of an area represented by an inset axes. diff --git a/lib/mpl_toolkits/mplot3d/axes3d.py b/lib/mpl_toolkits/mplot3d/axes3d.py index f9c7dc7f9416..2a4402b55dfe 100644 --- a/lib/mpl_toolkits/mplot3d/axes3d.py +++ b/lib/mpl_toolkits/mplot3d/axes3d.py @@ -19,7 +19,7 @@ import numpy as np -from matplotlib import _api, cbook, docstring, _preprocess_data +from matplotlib import _api, cbook, _docstring, _preprocess_data import matplotlib.artist as martist import matplotlib.axes as maxes import matplotlib.collections as mcoll @@ -40,7 +40,7 @@ from . import axis3d -@docstring.interpd +@_docstring.interpd @_api.define_aliases({ "xlim": ["xlim3d"], "ylim": ["ylim3d"], "zlim": ["zlim3d"]}) class Axes3D(Axes):