|
import functools |
|
import warnings |
|
from typing import Any, Callable, Type, TypeVar, cast |
|
|
|
class VersionedDeprecationWarning(UserWarning): |
|
"""A custom deprecation warning class that includes version information. |
|
|
|
Attributes: |
|
message (str): The deprecation message describing why the feature is deprecated. |
|
remove_version (str): The version in which the feature will be removed. |
|
|
|
Example: |
|
>>> def deprecated_function(): |
|
... warnings.warn( |
|
... VersionedDeprecationWarning( |
|
... "Function XYZ is deprecated.", |
|
... remove_version="2.0.0" |
|
... ) |
|
... ) |
|
... |
|
>>> deprecated_function() |
|
DeprecationWarning: Function XYZ is deprecated. It will be removed in version 2.0.0. |
|
""" |
|
|
|
def __init__(self, message: str, remove_version: str) -> None: |
|
super().__init__(message + f' It will be removed in version {remove_version}.') |
|
|
|
class ExperimentalWarning(Warning): |
|
"""A warning for experimental features. |
|
|
|
Attributes: |
|
feature_name (str): The name of the experimental feature. |
|
""" |
|
|
|
def __init__(self, feature_name: str) -> None: |
|
super().__init__(f'{feature_name} is experimental and may change with future versions.') |
|
F = TypeVar('F', bound=Callable[..., Any]) |
|
|
|
def experimental_function(feature_name: str) -> Callable[[F], F]: |
|
"""Decorator to mark a function as experimental. |
|
|
|
The message displayed will be {feature_name} is experimental and may change with future versions. |
|
|
|
Args: |
|
feature_name (str): The name of the experimental feature. |
|
|
|
Returns: |
|
The decorated function. |
|
""" |
|
|
|
def decorator(func: Callable): |
|
|
|
@functools.wraps(func) |
|
def wrapper(*args: Any, **kwargs: Any): |
|
warnings.warn(ExperimentalWarning(feature_name)) |
|
return func(*args, **kwargs) |
|
return cast(F, wrapper) |
|
return decorator |
|
|
|
def experimental_class(feature_name: str) -> Callable[[Type], Type]: |
|
"""Class decorator to mark a class as experimental.""" |
|
|
|
def class_decorator(cls: Type): |
|
original_init = cls.__init__ |
|
|
|
def new_init(self: Any, *args: Any, **kwargs: Any): |
|
warnings.warn(ExperimentalWarning(feature_name)) |
|
original_init(self, *args, **kwargs) |
|
cls.__init__ = new_init |
|
return cls |
|
return class_decorator |