From 55587494c08b270be49e01bce14bbe4dbaa17ba9 Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Sat, 4 May 2019 21:13:46 +0200 Subject: [PATCH] Add decorator to inherit keyword-only deprecations --- lib/matplotlib/cbook/__init__.py | 2 +- lib/matplotlib/cbook/deprecation.py | 51 ++++++++++++++++--- lib/matplotlib/pyplot.py | 79 +++++++++++++++++++++++++++++ lib/matplotlib/tests/test_cbook.py | 20 ++++++++ tools/boilerplate.py | 10 +++- 5 files changed, 154 insertions(+), 8 deletions(-) diff --git a/lib/matplotlib/cbook/__init__.py b/lib/matplotlib/cbook/__init__.py index bbeb82b18f1a..1fed8a88d653 100644 --- a/lib/matplotlib/cbook/__init__.py +++ b/lib/matplotlib/cbook/__init__.py @@ -35,7 +35,7 @@ from .deprecation import ( deprecated, warn_deprecated, _rename_parameter, _delete_parameter, _make_keyword_only, - _suppress_matplotlib_deprecation_warning, + _inherit_make_keyword_only, _suppress_matplotlib_deprecation_warning, MatplotlibDeprecationWarning, mplDeprecation) diff --git a/lib/matplotlib/cbook/deprecation.py b/lib/matplotlib/cbook/deprecation.py index cc7a26891b8f..364d5976d306 100644 --- a/lib/matplotlib/cbook/deprecation.py +++ b/lib/matplotlib/cbook/deprecation.py @@ -1,3 +1,4 @@ +from collections import namedtuple import contextlib import functools import inspect @@ -369,17 +370,15 @@ def wrapper(*args, **kwargs): return wrapper +_MakeKeyWordOnlyParams = namedtuple('_MakeKeyWordOnlyParams', + 'since, name, original_signature') + + def _make_keyword_only(since, name, func=None): """ Decorator indicating that passing parameter *name* (or any of the following ones) positionally to *func* is being deprecated. - - Note that this decorator **cannot** be applied to a function that has a - pyplot-level wrapper, as the wrapper always pass all arguments by keyword. - If it is used, users will see spurious DeprecationWarnings every time they - call the pyplot wrapper. """ - if func is None: return functools.partial(_make_keyword_only, since, name) @@ -408,6 +407,46 @@ def wrapper(*args, **kwargs): name=name, obj_type=f"parameter of {func.__name__}()") return func(*args, **kwargs) + wrapper._make_keyword_only_params = \ + _MakeKeyWordOnlyParams(since, name, signature) + + return wrapper + + +def _inherit_make_keyword_only(called_func, func=None): + """ + Decorator for inheriting _make_keyword_only decorator from *called_func*. + + This is used in pyplot to inherit the deprecation of positional parameter + use from the wrapped methods. + + Notes + ----- + The keyword_only warning of the *called_func* is suppressed. It's not + needed since the decorated function already checked the usage. + Additionally, this allows the pyplot wrapper to pass any currently + allowed positional keyword positionally to *called_func* (which is the + current implementation of the wrappers), without risking a warning from + the inner function. + """ + if func is None: + return functools.partial(_inherit_make_keyword_only, called_func) + + params = getattr(called_func, '_make_keyword_only_params', None) + if params is None: + return func + since, name, _ = params + + @_make_keyword_only(since, name) + @functools.wraps(func) + def wrapper(*args, **kwargs): + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", + f"Passing the {name} parameter .* positionally is deprecated", + MatplotlibDeprecationWarning) + return func(*args, **kwargs) + return wrapper diff --git a/lib/matplotlib/pyplot.py b/lib/matplotlib/pyplot.py index 111f003f6aed..fc854ca5928c 100644 --- a/lib/matplotlib/pyplot.py +++ b/lib/matplotlib/pyplot.py @@ -2281,6 +2281,7 @@ def getname_val(identifier): # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Figure.figimage) @docstring.copy(Figure.figimage) def figimage( X, xo=0, yo=0, alpha=None, norm=None, cmap=None, vmin=None, @@ -2291,6 +2292,7 @@ def figimage( # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Figure.text) @docstring.copy(Figure.text) def figtext( x, y, s, fontdict=None, @@ -2300,6 +2302,7 @@ def figtext( # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Figure.ginput) @docstring.copy(Figure.ginput) def ginput( n=1, timeout=30, show_clicks=True, mouse_add=1, mouse_pop=3, @@ -2311,18 +2314,21 @@ def ginput( # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Figure.suptitle) @docstring.copy(Figure.suptitle) def suptitle(t, **kwargs): return gcf().suptitle(t, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Figure.waitforbuttonpress) @docstring.copy(Figure.waitforbuttonpress) def waitforbuttonpress(timeout=-1): return gcf().waitforbuttonpress(timeout=timeout) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.acorr) @docstring.copy(Axes.acorr) def acorr(x, *, data=None, **kwargs): return gca().acorr( @@ -2330,6 +2336,7 @@ def acorr(x, *, data=None, **kwargs): # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.angle_spectrum) @docstring.copy(Axes.angle_spectrum) def angle_spectrum( x, Fs=None, Fc=None, window=None, pad_to=None, sides=None, *, @@ -2340,54 +2347,63 @@ def angle_spectrum( # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.annotate) @docstring.copy(Axes.annotate) def annotate(s, xy, *args, **kwargs): return gca().annotate(s, xy, *args, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.arrow) @docstring.copy(Axes.arrow) def arrow(x, y, dx, dy, **kwargs): return gca().arrow(x, y, dx, dy, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.autoscale) @docstring.copy(Axes.autoscale) def autoscale(enable=True, axis='both', tight=None): return gca().autoscale(enable=enable, axis=axis, tight=tight) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.axhline) @docstring.copy(Axes.axhline) def axhline(y=0, xmin=0, xmax=1, **kwargs): return gca().axhline(y=y, xmin=xmin, xmax=xmax, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.axhspan) @docstring.copy(Axes.axhspan) def axhspan(ymin, ymax, xmin=0, xmax=1, **kwargs): return gca().axhspan(ymin, ymax, xmin=xmin, xmax=xmax, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.axis) @docstring.copy(Axes.axis) def axis(*args, **kwargs): return gca().axis(*args, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.axvline) @docstring.copy(Axes.axvline) def axvline(x=0, ymin=0, ymax=1, **kwargs): return gca().axvline(x=x, ymin=ymin, ymax=ymax, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.axvspan) @docstring.copy(Axes.axvspan) def axvspan(xmin, xmax, ymin=0, ymax=1, **kwargs): return gca().axvspan(xmin, xmax, ymin=ymin, ymax=ymax, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.bar) @docstring.copy(Axes.bar) def bar( x, height, width=0.8, bottom=None, *, align='center', @@ -2398,6 +2414,7 @@ def bar( # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.barbs) @docstring.copy(Axes.barbs) def barbs(*args, data=None, **kw): return gca().barbs( @@ -2405,6 +2422,7 @@ def barbs(*args, data=None, **kw): # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.barh) @docstring.copy(Axes.barh) def barh(y, width, height=0.8, left=None, *, align='center', **kwargs): return gca().barh( @@ -2412,6 +2430,7 @@ def barh(y, width, height=0.8, left=None, *, align='center', **kwargs): # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.boxplot) @docstring.copy(Axes.boxplot) def boxplot( x, notch=None, sym=None, vert=None, whis=None, @@ -2437,6 +2456,7 @@ def boxplot( # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.broken_barh) @docstring.copy(Axes.broken_barh) def broken_barh(xranges, yrange, *, data=None, **kwargs): return gca().broken_barh( @@ -2445,18 +2465,21 @@ def broken_barh(xranges, yrange, *, data=None, **kwargs): # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.cla) @docstring.copy(Axes.cla) def cla(): return gca().cla() # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.clabel) @docstring.copy(Axes.clabel) def clabel(CS, *args, **kwargs): return gca().clabel(CS, *args, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.cohere) @docstring.copy(Axes.cohere) def cohere( x, y, NFFT=256, Fs=2, Fc=0, detrend=mlab.detrend_none, @@ -2470,6 +2493,7 @@ def cohere( # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.contour) @docstring.copy(Axes.contour) def contour(*args, data=None, **kwargs): __ret = gca().contour( @@ -2480,6 +2504,7 @@ def contour(*args, data=None, **kwargs): # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.contourf) @docstring.copy(Axes.contourf) def contourf(*args, data=None, **kwargs): __ret = gca().contourf( @@ -2490,6 +2515,7 @@ def contourf(*args, data=None, **kwargs): # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.csd) @docstring.copy(Axes.csd) def csd( x, y, NFFT=None, Fs=None, Fc=None, detrend=None, window=None, @@ -2503,6 +2529,7 @@ def csd( # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.errorbar) @docstring.copy(Axes.errorbar) def errorbar( x, y, yerr=None, xerr=None, fmt='', ecolor=None, @@ -2518,6 +2545,7 @@ def errorbar( # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.eventplot) @docstring.copy(Axes.eventplot) def eventplot( positions, orientation='horizontal', lineoffsets=1, @@ -2531,6 +2559,7 @@ def eventplot( # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.fill) @docstring.copy(Axes.fill) def fill(*args, data=None, **kwargs): return gca().fill( @@ -2539,6 +2568,7 @@ def fill(*args, data=None, **kwargs): # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.fill_between) @docstring.copy(Axes.fill_between) def fill_between( x, y1, y2=0, where=None, interpolate=False, step=None, *, @@ -2549,6 +2579,7 @@ def fill_between( # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.fill_betweenx) @docstring.copy(Axes.fill_betweenx) def fill_betweenx( y, x1, x2=0, where=None, step=None, interpolate=False, *, @@ -2559,12 +2590,14 @@ def fill_betweenx( # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.grid) @docstring.copy(Axes.grid) def grid(b=None, which='major', axis='both', **kwargs): return gca().grid(b=b, which=which, axis=axis, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.hexbin) @docstring.copy(Axes.hexbin) def hexbin( x, y, C=None, gridsize=100, bins=None, xscale='linear', @@ -2584,6 +2617,7 @@ def hexbin( # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.hist) @docstring.copy(Axes.hist) def hist( x, bins=None, range=None, density=None, weights=None, @@ -2600,6 +2634,7 @@ def hist( # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.hist2d) @docstring.copy(Axes.hist2d) def hist2d( x, y, bins=10, range=None, density=False, weights=None, @@ -2613,6 +2648,7 @@ def hist2d( # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.hlines) @docstring.copy(Axes.hlines) def hlines( y, xmin, xmax, colors='k', linestyles='solid', label='', *, @@ -2624,6 +2660,7 @@ def hlines( # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.imshow) @docstring.copy(Axes.imshow) def imshow( X, cmap=None, norm=None, aspect=None, interpolation=None, @@ -2643,24 +2680,28 @@ def imshow( # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.legend) @docstring.copy(Axes.legend) def legend(*args, **kwargs): return gca().legend(*args, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.locator_params) @docstring.copy(Axes.locator_params) def locator_params(axis='both', tight=None, **kwargs): return gca().locator_params(axis=axis, tight=tight, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.loglog) @docstring.copy(Axes.loglog) def loglog(*args, **kwargs): return gca().loglog(*args, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.magnitude_spectrum) @docstring.copy(Axes.magnitude_spectrum) def magnitude_spectrum( x, Fs=None, Fc=None, window=None, pad_to=None, sides=None, @@ -2672,24 +2713,28 @@ def magnitude_spectrum( # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.margins) @docstring.copy(Axes.margins) def margins(*margins, x=None, y=None, tight=True): return gca().margins(*margins, x=x, y=y, tight=tight) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.minorticks_off) @docstring.copy(Axes.minorticks_off) def minorticks_off(): return gca().minorticks_off() # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.minorticks_on) @docstring.copy(Axes.minorticks_on) def minorticks_on(): return gca().minorticks_on() # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.pcolor) @docstring.copy(Axes.pcolor) def pcolor( *args, alpha=None, norm=None, cmap=None, vmin=None, @@ -2703,6 +2748,7 @@ def pcolor( # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.pcolormesh) @docstring.copy(Axes.pcolormesh) def pcolormesh( *args, alpha=None, norm=None, cmap=None, vmin=None, @@ -2717,6 +2763,7 @@ def pcolormesh( # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.phase_spectrum) @docstring.copy(Axes.phase_spectrum) def phase_spectrum( x, Fs=None, Fc=None, window=None, pad_to=None, sides=None, *, @@ -2727,6 +2774,7 @@ def phase_spectrum( # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.pie) @docstring.copy(Axes.pie) def pie( x, explode=None, labels=None, colors=None, autopct=None, @@ -2745,6 +2793,7 @@ def pie( # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.plot) @docstring.copy(Axes.plot) def plot(*args, scalex=True, scaley=True, data=None, **kwargs): return gca().plot( @@ -2753,6 +2802,7 @@ def plot(*args, scalex=True, scaley=True, data=None, **kwargs): # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.plot_date) @docstring.copy(Axes.plot_date) def plot_date( x, y, fmt='o', tz=None, xdate=True, ydate=False, *, @@ -2763,6 +2813,7 @@ def plot_date( # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.psd) @docstring.copy(Axes.psd) def psd( x, NFFT=None, Fs=None, Fc=None, detrend=None, window=None, @@ -2776,6 +2827,7 @@ def psd( # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.quiver) @docstring.copy(Axes.quiver) def quiver(*args, data=None, **kw): __ret = gca().quiver( @@ -2785,12 +2837,14 @@ def quiver(*args, data=None, **kw): # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.quiverkey) @docstring.copy(Axes.quiverkey) def quiverkey(Q, X, Y, U, label, **kw): return gca().quiverkey(Q, X, Y, U, label, **kw) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.scatter) @docstring.copy(Axes.scatter) def scatter( x, y, s=None, c=None, marker=None, cmap=None, norm=None, @@ -2807,18 +2861,21 @@ def scatter( # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.semilogx) @docstring.copy(Axes.semilogx) def semilogx(*args, **kwargs): return gca().semilogx(*args, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.semilogy) @docstring.copy(Axes.semilogy) def semilogy(*args, **kwargs): return gca().semilogy(*args, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.specgram) @docstring.copy(Axes.specgram) def specgram( x, NFFT=None, Fs=None, Fc=None, detrend=None, window=None, @@ -2836,6 +2893,7 @@ def specgram( # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.spy) @docstring.copy(Axes.spy) def spy( Z, precision=0, marker=None, markersize=None, aspect='equal', @@ -2848,6 +2906,7 @@ def spy( # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.stackplot) @docstring.copy(Axes.stackplot) def stackplot( x, *args, labels=(), colors=None, baseline='zero', data=None, @@ -2858,6 +2917,7 @@ def stackplot( # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.stem) @docstring.copy(Axes.stem) def stem( *args, linefmt=None, markerfmt=None, basefmt=None, bottom=0, @@ -2870,6 +2930,7 @@ def stem( # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.step) @docstring.copy(Axes.step) def step(x, y, *args, where='pre', data=None, **kwargs): return gca().step( @@ -2878,6 +2939,7 @@ def step(x, y, *args, where='pre', data=None, **kwargs): # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.streamplot) @docstring.copy(Axes.streamplot) def streamplot( x, y, u, v, density=1, linewidth=None, color=None, cmap=None, @@ -2897,6 +2959,7 @@ def streamplot( # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.table) @docstring.copy(Axes.table) def table( cellText=None, cellColours=None, cellLoc='right', @@ -2913,6 +2976,7 @@ def table( # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.text) @docstring.copy(Axes.text) def text( x, y, s, fontdict=None, @@ -2921,12 +2985,14 @@ def text( # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.tick_params) @docstring.copy(Axes.tick_params) def tick_params(axis='both', **kwargs): return gca().tick_params(axis=axis, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.ticklabel_format) @docstring.copy(Axes.ticklabel_format) def ticklabel_format( *, axis='both', style='', scilimits=None, useOffset=None, @@ -2938,6 +3004,7 @@ def ticklabel_format( # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.tricontour) @docstring.copy(Axes.tricontour) def tricontour(*args, **kwargs): __ret = gca().tricontour(*args, **kwargs) @@ -2946,6 +3013,7 @@ def tricontour(*args, **kwargs): # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.tricontourf) @docstring.copy(Axes.tricontourf) def tricontourf(*args, **kwargs): __ret = gca().tricontourf(*args, **kwargs) @@ -2954,6 +3022,7 @@ def tricontourf(*args, **kwargs): # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.tripcolor) @docstring.copy(Axes.tripcolor) def tripcolor( *args, alpha=1.0, norm=None, cmap=None, vmin=None, vmax=None, @@ -2966,12 +3035,14 @@ def tripcolor( # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.triplot) @docstring.copy(Axes.triplot) def triplot(*args, **kwargs): return gca().triplot(*args, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.violinplot) @docstring.copy(Axes.violinplot) def violinplot( dataset, positions=None, vert=True, widths=0.5, @@ -2985,6 +3056,7 @@ def violinplot( # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.vlines) @docstring.copy(Axes.vlines) def vlines( x, ymin, ymax, colors='k', linestyles='solid', label='', *, @@ -2996,6 +3068,7 @@ def vlines( # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.xcorr) @docstring.copy(Axes.xcorr) def xcorr( x, y, normed=True, detrend=mlab.detrend_none, usevlines=True, @@ -3007,12 +3080,14 @@ def xcorr( # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes._sci) @docstring.copy(Axes._sci) def sci(im): return gca()._sci(im) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.set_title) @docstring.copy(Axes.set_title) def title(label, fontdict=None, loc=None, pad=None, **kwargs): return gca().set_title( @@ -3020,6 +3095,7 @@ def title(label, fontdict=None, loc=None, pad=None, **kwargs): # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.set_xlabel) @docstring.copy(Axes.set_xlabel) def xlabel(xlabel, fontdict=None, labelpad=None, **kwargs): return gca().set_xlabel( @@ -3027,6 +3103,7 @@ def xlabel(xlabel, fontdict=None, labelpad=None, **kwargs): # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.set_ylabel) @docstring.copy(Axes.set_ylabel) def ylabel(ylabel, fontdict=None, labelpad=None, **kwargs): return gca().set_ylabel( @@ -3034,12 +3111,14 @@ def ylabel(ylabel, fontdict=None, labelpad=None, **kwargs): # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.set_xscale) @docstring.copy(Axes.set_xscale) def xscale(value, **kwargs): return gca().set_xscale(value, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@cbook._inherit_make_keyword_only(Axes.set_yscale) @docstring.copy(Axes.set_yscale) def yscale(value, **kwargs): return gca().set_yscale(value, **kwargs) diff --git a/lib/matplotlib/tests/test_cbook.py b/lib/matplotlib/tests/test_cbook.py index 9d35b34c04b3..f4c1de9bc8a7 100644 --- a/lib/matplotlib/tests/test_cbook.py +++ b/lib/matplotlib/tests/test_cbook.py @@ -562,6 +562,26 @@ def func(pre, arg, post=None): func(1, 2, 3) +def test_inherit_make_keyword_only(recwarn): + @cbook._make_keyword_only("3.0", "arg") + def func(pre, arg, post=None): + pass + + @cbook._inherit_make_keyword_only(func) + def wrapper_func(pre, arg, post=None): + func(pre, arg, post=None) + + wrapper_func(1, arg=2) + for w in recwarn: + print(w) + assert len(recwarn) == 0 + + with pytest.warns(MatplotlibDeprecationWarning): + wrapper_func(1, 2) + with pytest.warns(MatplotlibDeprecationWarning): + wrapper_func(1, 2, 3) + + def test_warn_external(recwarn): cbook._warn_external("oops") assert len(recwarn) == 1 diff --git a/tools/boilerplate.py b/tools/boilerplate.py index caec5247410e..cfb15e900f1a 100644 --- a/tools/boilerplate.py +++ b/tools/boilerplate.py @@ -36,6 +36,7 @@ # Autogenerated by boilerplate.py. Do not edit as changes will be lost.""" AXES_CMAPPABLE_METHOD_TEMPLATE = AUTOGEN_MSG + """ +@cbook._inherit_make_keyword_only(Axes.{called_name}) @docstring.copy(Axes.{called_name}) def {name}{signature}: __ret = gca().{called_name}{call} @@ -44,12 +45,14 @@ def {name}{signature}: """ AXES_METHOD_TEMPLATE = AUTOGEN_MSG + """ +@cbook._inherit_make_keyword_only(Axes.{called_name}) @docstring.copy(Axes.{called_name}) def {name}{signature}: return gca().{called_name}{call} """ FIGURE_METHOD_TEMPLATE = AUTOGEN_MSG + """ +@cbook._inherit_make_keyword_only(Figure.{called_name}) @docstring.copy(Figure.{called_name}) def {name}{signature}: return gcf().{called_name}{call} @@ -121,7 +124,12 @@ def generate_function(name, called_fullname, template, **kwargs): class_name, called_name = called_fullname.split('.') class_ = {'Axes': Axes, 'Figure': Figure}[class_name] - signature = inspect.signature(getattr(class_, called_name)) + wrapped_func = getattr(class_, called_name) + mkwo_params = getattr(wrapped_func, '_make_keyword_only_params', None) + signature = (mkwo_params.original_signature + if mkwo_params is not None else + inspect.signature(wrapped_func)) + # Replace self argument. params = list(signature.parameters.values())[1:] signature = str(signature.replace(parameters=[