@@ -306,3 +306,60 @@ def wrapper(*args, **kwargs):
306
306
# pyplot would explicitly pass both arguments to the Axes method.
307
307
308
308
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
0 commit comments