|
| 1 | +from collections import namedtuple |
1 | 2 | import contextlib
|
2 | 3 | import functools
|
3 | 4 | import inspect
|
@@ -369,17 +370,15 @@ def wrapper(*args, **kwargs):
|
369 | 370 | return wrapper
|
370 | 371 |
|
371 | 372 |
|
| 373 | +_MakeKeyWordOnlyParams = namedtuple('_MakeKeyWordOnlyParams', |
| 374 | + 'since, name, original_signature') |
| 375 | + |
| 376 | + |
372 | 377 | def _make_keyword_only(since, name, func=None):
|
373 | 378 | """
|
374 | 379 | Decorator indicating that passing parameter *name* (or any of the following
|
375 | 380 | ones) positionally to *func* is being deprecated.
|
376 |
| -
|
377 |
| - Note that this decorator **cannot** be applied to a function that has a |
378 |
| - pyplot-level wrapper, as the wrapper always pass all arguments by keyword. |
379 |
| - If it is used, users will see spurious DeprecationWarnings every time they |
380 |
| - call the pyplot wrapper. |
381 | 381 | """
|
382 |
| - |
383 | 382 | if func is None:
|
384 | 383 | return functools.partial(_make_keyword_only, since, name)
|
385 | 384 |
|
@@ -408,6 +407,46 @@ def wrapper(*args, **kwargs):
|
408 | 407 | name=name, obj_type=f"parameter of {func.__name__}()")
|
409 | 408 | return func(*args, **kwargs)
|
410 | 409 |
|
| 410 | + wrapper._make_keyword_only_params = \ |
| 411 | + _MakeKeyWordOnlyParams(since, name, signature) |
| 412 | + |
| 413 | + return wrapper |
| 414 | + |
| 415 | + |
| 416 | +def _inherit_make_keyword_only(called_func, func=None): |
| 417 | + """ |
| 418 | + Decorator for inheriting _make_keyword_only decorator from *called_func*. |
| 419 | +
|
| 420 | + This is used in pyplot to inherit the deprecation of positional parameter |
| 421 | + use from the wrapped methods. |
| 422 | +
|
| 423 | + Notes |
| 424 | + ----- |
| 425 | + The keyword_only warning of the *called_func* is suppressed. It's not |
| 426 | + needed since the decorated function already checked the usage. |
| 427 | + Additionally, this allows the pyplot wrapper to pass any currently |
| 428 | + allowed positional keyword positionally to *called_func* (which is the |
| 429 | + current implementation of the wrappers), without risking a warning from |
| 430 | + the inner function. |
| 431 | + """ |
| 432 | + if func is None: |
| 433 | + return functools.partial(_inherit_make_keyword_only, called_func) |
| 434 | + |
| 435 | + params = getattr(called_func, '_make_keyword_only_params', None) |
| 436 | + if params is None: |
| 437 | + return func |
| 438 | + since, name, _ = params |
| 439 | + |
| 440 | + @_make_keyword_only(since, name) |
| 441 | + @functools.wraps(func) |
| 442 | + def wrapper(*args, **kwargs): |
| 443 | + with warnings.catch_warnings(): |
| 444 | + warnings.filterwarnings( |
| 445 | + "ignore", |
| 446 | + f"Passing the {name} parameter .* positionally is deprecated", |
| 447 | + MatplotlibDeprecationWarning) |
| 448 | + return func(*args, **kwargs) |
| 449 | + |
411 | 450 | return wrapper
|
412 | 451 |
|
413 | 452 |
|
|
0 commit comments