|
|
|
|
|
|
|
import functools |
|
import warnings |
|
from inspect import signature |
|
|
|
__all__ = ["deprecated"] |
|
|
|
|
|
class deprecated: |
|
"""Decorator to mark a function or class as deprecated. |
|
|
|
Issue a warning when the function is called/the class is instantiated and |
|
adds a warning to the docstring. |
|
|
|
The optional extra argument will be appended to the deprecation message |
|
and the docstring. Note: to use this with the default value for extra, put |
|
in an empty of parentheses: |
|
|
|
Examples |
|
-------- |
|
>>> from sklearn.utils import deprecated |
|
>>> deprecated() |
|
<sklearn.utils.deprecation.deprecated object at ...> |
|
>>> @deprecated() |
|
... def some_function(): pass |
|
|
|
Parameters |
|
---------- |
|
extra : str, default='' |
|
To be added to the deprecation messages. |
|
""" |
|
|
|
|
|
|
|
|
|
def __init__(self, extra=""): |
|
self.extra = extra |
|
|
|
def __call__(self, obj): |
|
"""Call method |
|
|
|
Parameters |
|
---------- |
|
obj : object |
|
""" |
|
if isinstance(obj, type): |
|
return self._decorate_class(obj) |
|
elif isinstance(obj, property): |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return self._decorate_property(obj) |
|
else: |
|
return self._decorate_fun(obj) |
|
|
|
def _decorate_class(self, cls): |
|
msg = "Class %s is deprecated" % cls.__name__ |
|
if self.extra: |
|
msg += "; %s" % self.extra |
|
|
|
new = cls.__new__ |
|
sig = signature(cls) |
|
|
|
def wrapped(cls, *args, **kwargs): |
|
warnings.warn(msg, category=FutureWarning) |
|
if new is object.__new__: |
|
return object.__new__(cls) |
|
|
|
return new(cls, *args, **kwargs) |
|
|
|
cls.__new__ = wrapped |
|
|
|
wrapped.__name__ = "__new__" |
|
wrapped.deprecated_original = new |
|
|
|
cls.__signature__ = sig |
|
|
|
return cls |
|
|
|
def _decorate_fun(self, fun): |
|
"""Decorate function fun""" |
|
|
|
msg = "Function %s is deprecated" % fun.__name__ |
|
if self.extra: |
|
msg += "; %s" % self.extra |
|
|
|
@functools.wraps(fun) |
|
def wrapped(*args, **kwargs): |
|
warnings.warn(msg, category=FutureWarning) |
|
return fun(*args, **kwargs) |
|
|
|
|
|
|
|
wrapped.__wrapped__ = fun |
|
|
|
return wrapped |
|
|
|
def _decorate_property(self, prop): |
|
msg = self.extra |
|
|
|
@property |
|
@functools.wraps(prop.fget) |
|
def wrapped(*args, **kwargs): |
|
warnings.warn(msg, category=FutureWarning) |
|
return prop.fget(*args, **kwargs) |
|
|
|
return wrapped |
|
|
|
|
|
def _is_deprecated(func): |
|
"""Helper to check if func is wrapped by our deprecated decorator""" |
|
closures = getattr(func, "__closure__", []) |
|
if closures is None: |
|
closures = [] |
|
is_deprecated = "deprecated" in "".join( |
|
[c.cell_contents for c in closures if isinstance(c.cell_contents, str)] |
|
) |
|
return is_deprecated |
|
|
|
|
|
|
|
def _deprecate_Xt_in_inverse_transform(X, Xt): |
|
"""Helper to deprecate the `Xt` argument in favor of `X` in inverse_transform.""" |
|
if X is not None and Xt is not None: |
|
raise TypeError("Cannot use both X and Xt. Use X only.") |
|
|
|
if X is None and Xt is None: |
|
raise TypeError("Missing required positional argument: X.") |
|
|
|
if Xt is not None: |
|
warnings.warn( |
|
"Xt was renamed X in version 1.5 and will be removed in 1.7.", |
|
FutureWarning, |
|
) |
|
return Xt |
|
|
|
return X |
|
|
|
|
|
|
|
|
|
def _deprecate_force_all_finite(force_all_finite, ensure_all_finite): |
|
"""Helper to deprecate force_all_finite in favor of ensure_all_finite.""" |
|
if force_all_finite != "deprecated": |
|
warnings.warn( |
|
"'force_all_finite' was renamed to 'ensure_all_finite' in 1.6 and will be " |
|
"removed in 1.8.", |
|
FutureWarning, |
|
) |
|
|
|
if ensure_all_finite is not None: |
|
raise ValueError( |
|
"'force_all_finite' and 'ensure_all_finite' cannot be used together. " |
|
"Pass `ensure_all_finite` only." |
|
) |
|
|
|
return force_all_finite |
|
|
|
if ensure_all_finite is None: |
|
return True |
|
|
|
return ensure_all_finite |
|
|