File size: 2,936 Bytes
b17c41e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
import functools
import warnings

from .settings_utils import get_constants

constants = get_constants()


class DeprecationError(Exception):
    """Custom exception for deprecated versions."""

    pass


def compare_versions(version1, version2):
    """Compare two semantic versioning strings and determine their relationship.

    Parameters:
    - version1 (str): The first version string to compare.
    - version2 (str): The second version string to compare.

    Returns:
    - int: -1 if version1 < version2, 1 if version1 > version2, 0 if equal.

    Example:
    >>> compare_versions("1.2.0", "1.2.3")
    -1
    >>> compare_versions("1.3.0", "1.2.8")
    1
    >>> compare_versions("1.0.0", "1.0.0")
    0
    """
    parts1 = [int(part) for part in version1.split(".")]
    parts2 = [int(part) for part in version2.split(".")]
    length_difference = len(parts1) - len(parts2)
    if length_difference > 0:
        parts2.extend([0] * length_difference)
    elif length_difference < 0:
        parts1.extend([0] * (-length_difference))
    for part1, part2 in zip(parts1, parts2):
        if part1 < part2:
            return -1
        if part1 > part2:
            return 1
    return 0


def depraction_wrapper(obj, version, alt_text):
    """A wrapper function for deprecation handling, issuing warnings or errors based on version comparison.

    Args:
        obj (callable): The object to be wrapped, typically a function or class method.
        version (str): The version at which the object becomes deprecated.
        alt_text (str): Additional text to display, usually suggests an alternative.

    Returns:
        callable: A wrapped version of the original object that checks for deprecation.
    """

    @functools.wraps(obj)
    def wrapper(*args, **kwargs):
        if constants.version < version:
            warnings.warn(
                f"{obj.__name__} is deprecated.", DeprecationWarning, stacklevel=2
            )
        elif constants.version >= version:
            raise DeprecationError(f"{obj.__name__} is no longer supported.{alt_text}")
        return obj(*args, **kwargs)

    return wrapper


def deprecation(version, alternative=None):
    """Decorator for marking functions or class methods as deprecated.

    Args:
        version (str): The version at which the function or method becomes deprecated.
        alternative (str, optional): Suggested alternative to the deprecated functionality.

    Returns:
        callable: A decorator that can be applied to functions or class methods.
    """

    def decorator(obj):
        alt_text = f" Use {alternative} instead." if alternative else ""
        if callable(obj):
            func = obj
        elif hasattr(obj, "__init__"):
            func = obj.__init__
        else:
            raise ValueError("Unsupported object type for deprecation.")
        return depraction_wrapper(func, version, alt_text)

    return decorator