| | import warnings |
| | from functools import wraps |
| | from inspect import Parameter, signature |
| | from typing import Iterable, Optional |
| |
|
| |
|
| | def _deprecate_positional_args(*, version: str): |
| | """Decorator for methods that issues warnings for positional arguments. |
| | Using the keyword-only argument syntax in pep 3102, arguments after the |
| | * will issue a warning when passed as a positional argument. |
| | |
| | Args: |
| | version (`str`): |
| | The version when positional arguments will result in error. |
| | """ |
| |
|
| | def _inner_deprecate_positional_args(f): |
| | sig = signature(f) |
| | kwonly_args = [] |
| | all_args = [] |
| | for name, param in sig.parameters.items(): |
| | if param.kind == Parameter.POSITIONAL_OR_KEYWORD: |
| | all_args.append(name) |
| | elif param.kind == Parameter.KEYWORD_ONLY: |
| | kwonly_args.append(name) |
| |
|
| | @wraps(f) |
| | def inner_f(*args, **kwargs): |
| | extra_args = len(args) - len(all_args) |
| | if extra_args <= 0: |
| | return f(*args, **kwargs) |
| | |
| | args_msg = [ |
| | f"{name}='{arg}'" if isinstance(arg, str) else f"{name}={arg}" |
| | for name, arg in zip(kwonly_args[:extra_args], args[-extra_args:]) |
| | ] |
| | args_msg = ", ".join(args_msg) |
| | warnings.warn( |
| | f"Deprecated positional argument(s) used in '{f.__name__}': pass" |
| | f" {args_msg} as keyword args. From version {version} passing these" |
| | " as positional arguments will result in an error,", |
| | FutureWarning, |
| | ) |
| | kwargs.update(zip(sig.parameters, args)) |
| | return f(**kwargs) |
| |
|
| | return inner_f |
| |
|
| | return _inner_deprecate_positional_args |
| |
|
| |
|
| | def _deprecate_arguments( |
| | *, |
| | version: str, |
| | deprecated_args: Iterable[str], |
| | custom_message: Optional[str] = None, |
| | ): |
| | """Decorator to issue warnings when using deprecated arguments. |
| | |
| | TODO: could be useful to be able to set a custom error message. |
| | |
| | Args: |
| | version (`str`): |
| | The version when deprecated arguments will result in error. |
| | deprecated_args (`List[str]`): |
| | List of the arguments to be deprecated. |
| | custom_message (`str`, *optional*): |
| | Warning message that is raised. If not passed, a default warning message |
| | will be created. |
| | """ |
| |
|
| | def _inner_deprecate_positional_args(f): |
| | sig = signature(f) |
| |
|
| | @wraps(f) |
| | def inner_f(*args, **kwargs): |
| | |
| | used_deprecated_args = [] |
| | for _, parameter in zip(args, sig.parameters.values()): |
| | if parameter.name in deprecated_args: |
| | used_deprecated_args.append(parameter.name) |
| | for kwarg_name, kwarg_value in kwargs.items(): |
| | if ( |
| | |
| | kwarg_name in deprecated_args |
| | |
| | and kwarg_value != sig.parameters[kwarg_name].default |
| | ): |
| | used_deprecated_args.append(kwarg_name) |
| |
|
| | |
| | if len(used_deprecated_args) > 0: |
| | message = ( |
| | f"Deprecated argument(s) used in '{f.__name__}':" |
| | f" {', '.join(used_deprecated_args)}. Will not be supported from" |
| | f" version '{version}'." |
| | ) |
| | if custom_message is not None: |
| | message += "\n\n" + custom_message |
| | warnings.warn(message, FutureWarning) |
| | return f(*args, **kwargs) |
| |
|
| | return inner_f |
| |
|
| | return _inner_deprecate_positional_args |
| |
|
| |
|
| | def _deprecate_method(*, version: str, message: Optional[str] = None): |
| | """Decorator to issue warnings when using a deprecated method. |
| | |
| | Args: |
| | version (`str`): |
| | The version when deprecated arguments will result in error. |
| | message (`str`, *optional*): |
| | Warning message that is raised. If not passed, a default warning message |
| | will be created. |
| | """ |
| |
|
| | def _inner_deprecate_method(f): |
| | name = f.__name__ |
| | if name == "__init__": |
| | name = f.__qualname__.split(".")[0] |
| |
|
| | @wraps(f) |
| | def inner_f(*args, **kwargs): |
| | warning_message = ( |
| | f"'{name}' (from '{f.__module__}') is deprecated and will be removed from version '{version}'." |
| | ) |
| | if message is not None: |
| | warning_message += " " + message |
| | warnings.warn(warning_message, FutureWarning) |
| | return f(*args, **kwargs) |
| |
|
| | return inner_f |
| |
|
| | return _inner_deprecate_method |
| |
|