From 8f855a6904bfb5be970d4faaba78d1e9e8fba364 Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Mon, 9 Sep 2024 16:17:15 +0200 Subject: [PATCH 1/2] MNT: Make Substitution and _ArtistPropertiesSubstitution independent They do not have relevant functional overlap. Thus, it's simpler to keep them completely separated. --- lib/matplotlib/_docstring.py | 17 +++++++++-------- lib/matplotlib/_docstring.pyi | 3 ++- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/lib/matplotlib/_docstring.py b/lib/matplotlib/_docstring.py index 6c80b080af4c..5ec19c08ef1b 100644 --- a/lib/matplotlib/_docstring.py +++ b/lib/matplotlib/_docstring.py @@ -68,12 +68,6 @@ def __call__(self, func): 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): @@ -89,7 +83,7 @@ def __missing__(self, key): return self.setdefault(key, kwdoc(cls)) -class _ArtistPropertiesSubstitution(Substitution): +class _ArtistPropertiesSubstitution: """ A `.Substitution` with two additional features: @@ -104,8 +98,15 @@ class _ArtistPropertiesSubstitution(Substitution): def __init__(self): self.params = _ArtistKwdocLoader() + def update(self, *args, **kwargs): + """ + Update ``self.params`` (which must be a dict) with the supplied args. + """ + self.params.update(*args, **kwargs) + def __call__(self, obj): - super().__call__(obj) + if obj.__doc__: + obj.__doc__ = inspect.cleandoc(obj.__doc__) % self.params if isinstance(obj, type) and obj.__init__ != object.__init__: self(obj.__init__) return obj diff --git a/lib/matplotlib/_docstring.pyi b/lib/matplotlib/_docstring.pyi index 62cea3da4476..b776d4b4dbe3 100644 --- a/lib/matplotlib/_docstring.pyi +++ b/lib/matplotlib/_docstring.pyi @@ -21,8 +21,9 @@ class _ArtistKwdocLoader(dict[str, str]): def __missing__(self, key: str) -> str: ... -class _ArtistPropertiesSubstitution(Substitution): +class _ArtistPropertiesSubstitution: def __init__(self) -> None: ... + def update(self, *args, **kwargs) -> None: def __call__(self, obj: _T) -> _T: ... From fe9479aae97b24868a81f5e0150a929945865ddf Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Mon, 9 Sep 2024 17:05:30 +0200 Subject: [PATCH 2/2] Rename _ArtistPropertiesSubstitution.update() to register() While it's internally a dict.update. The logical process is a registration to make the names publically available. Also, remove the possibility to pass a dict. Passing kwargs is enough and we can simplify the API to only one type of usage. --- lib/matplotlib/_docstring.py | 37 ++++++++++++++++++-------- lib/matplotlib/_docstring.pyi | 2 +- lib/matplotlib/_enums.py | 6 +++-- lib/matplotlib/axes/_secondary_axes.py | 2 +- lib/matplotlib/cm.py | 2 +- lib/matplotlib/colorbar.py | 2 +- lib/matplotlib/contour.py | 4 +-- lib/matplotlib/legend.py | 8 +++--- lib/matplotlib/mlab.py | 2 +- lib/matplotlib/patches.py | 4 +-- lib/matplotlib/projections/__init__.py | 2 +- lib/matplotlib/quiver.py | 4 +-- lib/matplotlib/scale.py | 2 +- lib/matplotlib/text.py | 2 +- lib/matplotlib/tri/_tricontour.py | 2 +- 15 files changed, 49 insertions(+), 32 deletions(-) diff --git a/lib/matplotlib/_docstring.py b/lib/matplotlib/_docstring.py index 5ec19c08ef1b..f16c0bb8f0ef 100644 --- a/lib/matplotlib/_docstring.py +++ b/lib/matplotlib/_docstring.py @@ -85,24 +85,39 @@ def __missing__(self, key): class _ArtistPropertiesSubstitution: """ - 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). + A class to substitute formatted placeholders in docstrings. + + This is realized in a single instance ``_docstring.interpd``. + + Use `~._ArtistPropertiesSubstition.register` to define placeholders and + their substitution, e.g. ``_docstring.interpd.register(name="some value")``. + + Use this as a decorator to apply the substitution:: + + @_docstring.interpd + def some_func(): + '''Replace %(name)s.''' + + 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). + + 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. """ def __init__(self): self.params = _ArtistKwdocLoader() - def update(self, *args, **kwargs): + def register(self, **kwargs): """ - Update ``self.params`` (which must be a dict) with the supplied args. + Register substitutions. + + ``_docstring.interpd.register(name="some value")`` makes "name" available + as a named parameter that will be replaced by "some value". """ - self.params.update(*args, **kwargs) + self.params.update(**kwargs) def __call__(self, obj): if obj.__doc__: diff --git a/lib/matplotlib/_docstring.pyi b/lib/matplotlib/_docstring.pyi index b776d4b4dbe3..fb52d0846123 100644 --- a/lib/matplotlib/_docstring.pyi +++ b/lib/matplotlib/_docstring.pyi @@ -23,7 +23,7 @@ class _ArtistKwdocLoader(dict[str, str]): class _ArtistPropertiesSubstitution: def __init__(self) -> None: ... - def update(self, *args, **kwargs) -> None: + def register(self, **kwargs) -> None: ... def __call__(self, obj: _T) -> _T: ... diff --git a/lib/matplotlib/_enums.py b/lib/matplotlib/_enums.py index c8c50f7c3028..773011d36bf6 100644 --- a/lib/matplotlib/_enums.py +++ b/lib/matplotlib/_enums.py @@ -181,5 +181,7 @@ def demo(): + ", ".join([f"'{cs.name}'" for cs in CapStyle]) \ + "}" -_docstring.interpd.update({'JoinStyle': JoinStyle.input_description, - 'CapStyle': CapStyle.input_description}) +_docstring.interpd.register( + JoinStyle=JoinStyle.input_description, + CapStyle=CapStyle.input_description, +) diff --git a/lib/matplotlib/axes/_secondary_axes.py b/lib/matplotlib/axes/_secondary_axes.py index b01acc4b127d..15a1970fa4a6 100644 --- a/lib/matplotlib/axes/_secondary_axes.py +++ b/lib/matplotlib/axes/_secondary_axes.py @@ -319,4 +319,4 @@ def set_color(self, color): **kwargs : `~matplotlib.axes.Axes` properties. Other miscellaneous Axes parameters. ''' -_docstring.interpd.update(_secax_docstring=_secax_docstring) +_docstring.interpd.register(_secax_docstring=_secax_docstring) diff --git a/lib/matplotlib/cm.py b/lib/matplotlib/cm.py index 025cb84db1d7..27333f8dba8a 100644 --- a/lib/matplotlib/cm.py +++ b/lib/matplotlib/cm.py @@ -651,7 +651,7 @@ def _format_cursor_data_override(self, data): # The docstrings here must be generic enough to apply to all relevant methods. -mpl._docstring.interpd.update( +mpl._docstring.interpd.register( cmap_doc="""\ cmap : str or `~matplotlib.colors.Colormap`, default: :rc:`image.cmap` The Colormap instance or registered colormap name used to map scalar data diff --git a/lib/matplotlib/colorbar.py b/lib/matplotlib/colorbar.py index 296f072a4af1..2d2fe42dd16a 100644 --- a/lib/matplotlib/colorbar.py +++ b/lib/matplotlib/colorbar.py @@ -26,7 +26,7 @@ _log = logging.getLogger(__name__) -_docstring.interpd.update( +_docstring.interpd.register( _make_axes_kw_doc=""" location : None or {'left', 'right', 'top', 'bottom'} The location, relative to the parent Axes, where the colorbar Axes diff --git a/lib/matplotlib/contour.py b/lib/matplotlib/contour.py index 9ad4cd4f2752..cb8846688372 100644 --- a/lib/matplotlib/contour.py +++ b/lib/matplotlib/contour.py @@ -536,7 +536,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.register(contour_set_attributes=r""" Attributes ---------- ax : `~matplotlib.axes.Axes` @@ -1445,7 +1445,7 @@ def _initialize_x_y(self, z): return np.meshgrid(x, y) -_docstring.interpd.update(contour_doc=""" +_docstring.interpd.register(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/legend.py b/lib/matplotlib/legend.py index 7ef328e2007c..f411a4c118dd 100644 --- a/lib/matplotlib/legend.py +++ b/lib/matplotlib/legend.py @@ -305,7 +305,7 @@ def _update_bbox_to_anchor(self, loc_in_canvas): _loc_doc_base.format(parent='axes', default=':rc:`legend.loc`', best=_loc_doc_best, outside='') + _legend_kw_doc_base) -_docstring.interpd.update(_legend_kw_axes=_legend_kw_axes_st) +_docstring.interpd.register(_legend_kw_axes=_legend_kw_axes_st) _outside_doc = """ If a figure is using the constrained layout manager, the string codes @@ -323,20 +323,20 @@ def _update_bbox_to_anchor(self, loc_in_canvas): _loc_doc_base.format(parent='figure', default="'upper right'", best='', outside=_outside_doc) + _legend_kw_doc_base) -_docstring.interpd.update(_legend_kw_figure=_legend_kw_figure_st) +_docstring.interpd.register(_legend_kw_figure=_legend_kw_figure_st) _legend_kw_both_st = ( _loc_doc_base.format(parent='axes/figure', default=":rc:`legend.loc` for Axes, 'upper right' for Figure", best=_loc_doc_best, outside=_outside_doc) + _legend_kw_doc_base) -_docstring.interpd.update(_legend_kw_doc=_legend_kw_both_st) +_docstring.interpd.register(_legend_kw_doc=_legend_kw_both_st) _legend_kw_set_loc_st = ( _loc_doc_base.format(parent='axes/figure', default=":rc:`legend.loc` for Axes, 'upper right' for Figure", best=_loc_doc_best, outside=_outside_doc)) -_docstring.interpd.update(_legend_kw_set_loc_doc=_legend_kw_set_loc_st) +_docstring.interpd.register(_legend_kw_set_loc_doc=_legend_kw_set_loc_st) class Legend(Artist): diff --git a/lib/matplotlib/mlab.py b/lib/matplotlib/mlab.py index e1f08c0da5ce..7b774a80afa5 100644 --- a/lib/matplotlib/mlab.py +++ b/lib/matplotlib/mlab.py @@ -400,7 +400,7 @@ def _single_spectrum_helper( # Split out these keyword docs so that they can be used elsewhere -_docstring.interpd.update( +_docstring.interpd.register( Spectral="""\ Fs : float, default: 2 The sampling frequency (samples per time unit). It is used to calculate diff --git a/lib/matplotlib/patches.py b/lib/matplotlib/patches.py index 0d5867e08ae1..b5be4e9cfab0 100644 --- a/lib/matplotlib/patches.py +++ b/lib/matplotlib/patches.py @@ -1552,7 +1552,7 @@ def _make_verts(self): ] -_docstring.interpd.update( +_docstring.interpd.register( FancyArrow="\n".join( (inspect.getdoc(FancyArrow.__init__) or "").splitlines()[2:])) @@ -2290,7 +2290,7 @@ def __init_subclass__(cls): # - %(BoxStyle:table_and_accepts)s # - %(ConnectionStyle:table_and_accepts)s # - %(ArrowStyle:table_and_accepts)s - _docstring.interpd.update({ + _docstring.interpd.register(**{ f"{cls.__name__}:table": cls.pprint_styles(), f"{cls.__name__}:table_and_accepts": ( cls.pprint_styles() diff --git a/lib/matplotlib/projections/__init__.py b/lib/matplotlib/projections/__init__.py index b58d1ceb754d..f7b46192a84e 100644 --- a/lib/matplotlib/projections/__init__.py +++ b/lib/matplotlib/projections/__init__.py @@ -123,4 +123,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.register(projection_names=get_projection_names()) diff --git a/lib/matplotlib/quiver.py b/lib/matplotlib/quiver.py index 16c8a2195f67..c7408476c784 100644 --- a/lib/matplotlib/quiver.py +++ b/lib/matplotlib/quiver.py @@ -230,7 +230,7 @@ of the head in forward direction so that the arrow head looks broken. """ % _docstring.interpd.params -_docstring.interpd.update(quiver_doc=_quiver_doc) +_docstring.interpd.register(quiver_doc=_quiver_doc) class QuiverKey(martist.Artist): @@ -865,7 +865,7 @@ def _h_arrows(self, length): %(PolyCollection:kwdoc)s """ % _docstring.interpd.params -_docstring.interpd.update(barbs_doc=_barbs_doc) +_docstring.interpd.register(barbs_doc=_barbs_doc) class Barbs(mcollections.PolyCollection): diff --git a/lib/matplotlib/scale.py b/lib/matplotlib/scale.py index 7f90362b574b..d80ef9828fcd 100644 --- a/lib/matplotlib/scale.py +++ b/lib/matplotlib/scale.py @@ -750,7 +750,7 @@ def _get_scale_docs(): return "\n".join(docs) -_docstring.interpd.update( +_docstring.interpd.register( scale_type='{%s}' % ', '.join([repr(x) for x in get_scale_names()]), scale_docs=_get_scale_docs().rstrip(), ) diff --git a/lib/matplotlib/text.py b/lib/matplotlib/text.py index 6f59ca669d21..825e33d09add 100644 --- a/lib/matplotlib/text.py +++ b/lib/matplotlib/text.py @@ -2030,4 +2030,4 @@ def get_tightbbox(self, renderer=None): return super().get_tightbbox(renderer) -_docstring.interpd.update(Annotation=Annotation.__init__.__doc__) +_docstring.interpd.register(Annotation=Annotation.__init__.__doc__) diff --git a/lib/matplotlib/tri/_tricontour.py b/lib/matplotlib/tri/_tricontour.py index 1db3715d01af..bf96a8eb42a3 100644 --- a/lib/matplotlib/tri/_tricontour.py +++ b/lib/matplotlib/tri/_tricontour.py @@ -79,7 +79,7 @@ def _contour_args(self, args, kwargs): return (tri, z) -_docstring.interpd.update(_tricontour_doc=""" +_docstring.interpd.register(_tricontour_doc=""" Draw contour %%(type)s on an unstructured triangular grid. Call signatures:: pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy