Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit e90d264

Browse files
committed
Decorator for deleting a parameter with a deprecation period.
As an example application, deprecate the unused shape and imlim args to imshow() (unused since around 4d1107c (2006)).
1 parent 45a3ea1 commit e90d264

File tree

7 files changed

+85
-6
lines changed

7 files changed

+85
-6
lines changed

doc/api/next_api_changes/2018-01-10-AL.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,8 @@ Changes in parameter names
99
In each case, the old argument name remains supported (it cannot be used
1010
simultaneously with the new name), but suppport for it will be dropped in
1111
Matplotlib 3.3.
12+
13+
- The unused ``shape`` and ``imlim`` parameters to `Axes.imshow` are
14+
deprecated. To avoid triggering the deprecation warning, the ``filternorm``,
15+
``filterrad``, ``resample``, and ``url`` arguments should be passed by
16+
keyword.

lib/matplotlib/axes/_axes.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5390,6 +5390,8 @@ def get_interp_point(ind):
53905390

53915391
#### plotting z(x,y): imshow, pcolor and relatives, contour
53925392
@_preprocess_data()
5393+
@cbook._delete_parameter("3.1", "shape")
5394+
@cbook._delete_parameter("3.1", "imlim")
53935395
def imshow(self, X, cmap=None, norm=None, aspect=None,
53945396
interpolation=None, alpha=None, vmin=None, vmax=None,
53955397
origin=None, extent=None, shape=None, filternorm=1,
@@ -5506,9 +5508,6 @@ def imshow(self, X, cmap=None, norm=None, aspect=None,
55065508
See the example :doc:`/tutorials/intermediate/imshow_extent` for a
55075509
more detailed description.
55085510
5509-
shape : scalars (columns, rows), optional, default: None
5510-
For raw buffer images.
5511-
55125511
filternorm : bool, optional, default: True
55135512
A parameter for the antigrain image resize filter (see the
55145513
antigrain documentation). If *filternorm* is set, the filter

lib/matplotlib/cbook/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232

3333
import matplotlib
3434
from .deprecation import (
35-
deprecated, warn_deprecated, _rename_parameter,
35+
deprecated, warn_deprecated, _rename_parameter, _delete_parameter,
3636
MatplotlibDeprecationWarning, mplDeprecation)
3737

3838

lib/matplotlib/cbook/deprecation.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,3 +306,60 @@ def wrapper(*args, **kwargs):
306306
# pyplot would explicitly pass both arguments to the Axes method.
307307

308308
return wrapper
309+
310+
311+
class _deprecated_parameter_class:
312+
def __repr__(self):
313+
return "<deprecated parameter>"
314+
315+
316+
_deprecated_parameter = _deprecated_parameter_class()
317+
318+
319+
def _delete_parameter(since, name, func=None):
320+
"""
321+
Decorator indicating that parameter *name* of *func* is being deprecated.
322+
323+
The actual implementation of *func* should keep the *name* parameter in its
324+
signature.
325+
326+
Parameters that come after the deprecated parameter effectively become
327+
keyword-only (as they cannot be passed positionally without triggering the
328+
DeprecationWarning on the deprecated parameter), and should be marked as
329+
such after the deprecation period has passed and the deprecated parameter
330+
is removed.
331+
332+
Examples
333+
--------
334+
335+
::
336+
@_delete_parameter("3.1", "unused")
337+
def func(used_arg, other_arg, unused, more_args): ...
338+
"""
339+
340+
if func is None:
341+
return functools.partial(_delete_parameter, since, name)
342+
343+
signature = inspect.signature(func)
344+
assert name in signature.parameters, (
345+
f"Matplotlib internal error: {name!r} must be a parameter for "
346+
f"{func.__name__}()")
347+
func.__signature__ = signature.replace(parameters=[
348+
param.replace(default=_deprecated_parameter) if param.name == name
349+
else param
350+
for param in signature.parameters.values()])
351+
352+
@functools.wraps(func)
353+
def wrapper(*args, **kwargs):
354+
arguments = func.__signature__.bind(*args, **kwargs).arguments
355+
# We cannot just check `name not in arguments` because the pyplot
356+
# wrappers always pass all arguments explicitly.
357+
if name in arguments and arguments[name] != _deprecated_parameter:
358+
warn_deprecated(
359+
since, message=f"The {name!r} parameter of {func.__name__}() "
360+
f"is deprecated since Matplotlib {since} and will be removed "
361+
f"%(removal)s. If any parameter follows {name!r}, they "
362+
f"should be pass as keyword, not positionally.")
363+
return func(*args, **kwargs)
364+
365+
return wrapper

lib/matplotlib/pyplot.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2657,7 +2657,8 @@ def hlines(
26572657
def imshow(
26582658
X, cmap=None, norm=None, aspect=None, interpolation=None,
26592659
alpha=None, vmin=None, vmax=None, origin=None, extent=None,
2660-
shape=None, filternorm=1, filterrad=4.0, imlim=None,
2660+
shape=cbook.deprecation._deprecated_parameter, filternorm=1,
2661+
filterrad=4.0, imlim=cbook.deprecation._deprecated_parameter,
26612662
resample=None, url=None, *, data=None, **kwargs):
26622663
__ret = gca().imshow(
26632664
X, cmap=cmap, norm=norm, aspect=aspect,

lib/matplotlib/tests/test_image.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
from matplotlib import (
1616
colors, image as mimage, patches, pyplot as plt,
1717
rc_context, rcParams)
18+
from matplotlib.cbook import MatplotlibDeprecationWarning
1819
from matplotlib.image import (AxesImage, BboxImage, FigureImage,
1920
NonUniformImage, PcolorImage)
2021
from matplotlib.testing.decorators import image_comparison
@@ -936,3 +937,17 @@ def test_relim():
936937
ax.relim()
937938
ax.autoscale()
938939
assert ax.get_xlim() == ax.get_ylim() == (0, 1)
940+
941+
942+
def test_deprecation():
943+
data = [[1, 2], [3, 4]]
944+
ax = plt.figure().subplots()
945+
for obj in [ax, plt]:
946+
with pytest.warns(None) as record:
947+
obj.imshow(data)
948+
assert len(record) == 0
949+
with pytest.warns(MatplotlibDeprecationWarning):
950+
obj.imshow(data, shape=None)
951+
with pytest.warns(MatplotlibDeprecationWarning):
952+
# Enough arguments to pass "shape" positionally.
953+
obj.imshow(data, *[None] * 10)

tools/boilerplate.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
# This line imports the installed copy of matplotlib, and not the local copy.
2222
import numpy as np
23-
from matplotlib import mlab
23+
from matplotlib import cbook, mlab
2424
from matplotlib.axes import Axes
2525

2626

@@ -175,6 +175,8 @@ def __init__(self, value):
175175
self._repr = "mlab.window_hanning"
176176
elif value is np.mean:
177177
self._repr = "np.mean"
178+
elif value is cbook.deprecation._deprecated_parameter:
179+
self._repr = "cbook.deprecation._deprecated_parameter"
178180
else:
179181
self._repr = repr(value)
180182

0 commit comments

Comments
 (0)