| import enum |
| import inspect |
| import warnings |
| from functools import wraps |
| from typing import Callable, Optional |
|
|
| from .logging import get_logger |
|
|
|
|
| _emitted_deprecation_warnings = set() |
| logger = get_logger(__name__) |
|
|
|
|
| def deprecated(help_message: Optional[str] = None): |
| """Decorator to mark a class or a function as deprecated. |
| |
| Args: |
| help_message (:obj:`str`, optional): An optional message to guide the user on how to |
| switch to non-deprecated usage of the library. |
| """ |
|
|
| def decorator(deprecated_class_or_function: Callable): |
| global _emitted_deprecation_warnings |
|
|
| if inspect.isclass(deprecated_class_or_function): |
| deprecated_function = deprecated_class_or_function.__init__ |
| name = deprecated_class_or_function.__name__ |
| else: |
| deprecated_function = deprecated_class_or_function |
| name = deprecated_function.__name__ |
| |
| name = name if name != "__init__" else deprecated_function.__qualname__.split(".")[-2] |
|
|
| warning_msg = ( |
| f"{name} is deprecated and will be removed in the next major version of datasets." + f" {help_message}" |
| if help_message |
| else "" |
| ) |
|
|
| @wraps(deprecated_function) |
| def wrapper(*args, **kwargs): |
| func_hash = hash(deprecated_function) |
| if func_hash not in _emitted_deprecation_warnings: |
| warnings.warn(warning_msg, category=FutureWarning, stacklevel=2) |
| _emitted_deprecation_warnings.add(func_hash) |
| return deprecated_function(*args, **kwargs) |
|
|
| wrapper._decorator_name_ = "deprecated" |
|
|
| if inspect.isclass(deprecated_class_or_function): |
| deprecated_class_or_function.__init__ = wrapper |
| return deprecated_class_or_function |
| else: |
| return wrapper |
|
|
| return decorator |
|
|
|
|
| class OnAccess(enum.EnumMeta): |
| """ |
| Enum metaclass that calls a user-specified function whenever a member is accessed. |
| """ |
|
|
| def __getattribute__(cls, name): |
| obj = super().__getattribute__(name) |
| if isinstance(obj, enum.Enum) and obj._on_access: |
| obj._on_access() |
| return obj |
|
|
| def __getitem__(cls, name): |
| member = super().__getitem__(name) |
| if member._on_access: |
| member._on_access() |
| return member |
|
|
| def __call__(cls, value, names=None, *, module=None, qualname=None, type=None, start=1): |
| obj = super().__call__(value, names, module=module, qualname=qualname, type=type, start=start) |
| if isinstance(obj, enum.Enum) and obj._on_access: |
| obj._on_access() |
| return obj |
|
|
|
|
| class DeprecatedEnum(enum.Enum, metaclass=OnAccess): |
| """ |
| Enum class that calls `deprecate` method whenever a member is accessed. |
| """ |
|
|
| def __new__(cls, value): |
| member = object.__new__(cls) |
| member._value_ = value |
| member._on_access = member.deprecate |
| return member |
|
|
| @property |
| def help_message(self): |
| return "" |
|
|
| def deprecate(self): |
| help_message = f" {self.help_message}" if self.help_message else "" |
| warnings.warn( |
| f"'{self.__objclass__.__name__}' is deprecated and will be removed in the next major version of datasets." |
| + help_message, |
| FutureWarning, |
| stacklevel=3, |
| ) |
|
|