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