Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
decor.py234 linesDownload Raw Back to utils
1"""2passlib.utils.decor -- helper decorators & properties3"""4#=============================================================================5# imports6#=============================================================================7# core8from __future__ import absolute_import, division, print_function9import logging10log = logging.getLogger(__name__)11from functools import wraps, update_wrapper12import types13from warnings import warn14# site15# pkg16from passlib.utils.compat import PY317# local18__all__ = [19    "classproperty",20    "hybrid_method",21 22    "memoize_single_value",23    "memoized_property",24 25    "deprecated_function",26    "deprecated_method",27]28 29#=============================================================================30# class-level decorators31#=============================================================================32class classproperty(object):33    """Function decorator which acts like a combination of classmethod+property (limited to read-only properties)"""34 35    def __init__(self, func):36        self.im_func = func37 38    def __get__(self, obj, cls):39        return self.im_func(cls)40 41    @property42    def __func__(self):43        """py3 compatible alias"""44        return self.im_func45 46class hybrid_method(object):47    """48    decorator which invokes function with class if called as class method,49    and with object if called at instance level.50    """51 52    def __init__(self, func):53        self.func = func54        update_wrapper(self, func)55 56    def __get__(self, obj, cls):57        if obj is None:58            obj = cls59        if PY3:60            return types.MethodType(self.func, obj)61        else:62            return types.MethodType(self.func, obj, cls)63 64#=============================================================================65# memoization66#=============================================================================67 68def memoize_single_value(func):69    """70    decorator for function which takes no args,71    and memoizes result.  exposes a ``.clear_cache`` method72    to clear the cached value.73    """74    cache = {}75 76    @wraps(func)77    def wrapper():78        try:79            return cache[True]80        except KeyError:81            pass82        value = cache[True] = func()83        return value84 85    def clear_cache():86        cache.pop(True, None)87    wrapper.clear_cache = clear_cache88 89    return wrapper90 91class memoized_property(object):92    """93    decorator which invokes method once, then replaces attr with result94    """95    def __init__(self, func):96        self.__func__ = func97        self.__name__ = func.__name__98        self.__doc__ = func.__doc__99 100    def __get__(self, obj, cls):101        if obj is None:102            return self103        value = self.__func__(obj)104        setattr(obj, self.__name__, value)105        return value106 107    if not PY3:108 109        @property110        def im_func(self):111            """py2 alias"""112            return self.__func__113 114    def clear_cache(self, obj):115        """116        class-level helper to clear stored value (if any).117 118        usage: :samp:`type(self).{attr}.clear_cache(self)`119        """120        obj.__dict__.pop(self.__name__, None)121 122    def peek_cache(self, obj, default=None):123        """124        class-level helper to peek at stored value125 126        usage: :samp:`value = type(self).{attr}.clear_cache(self)`127        """128        return obj.__dict__.get(self.__name__, default)129 130# works but not used131##class memoized_class_property(object):132##    """function decorator which calls function as classmethod,133##    and replaces itself with result for current and all future invocations.134##    """135##    def __init__(self, func):136##        self.im_func = func137##138##    def __get__(self, obj, cls):139##        func = self.im_func140##        value = func(cls)141##        setattr(cls, func.__name__, value)142##        return value143##144##    @property145##    def __func__(self):146##        "py3 compatible alias"147 148#=============================================================================149# deprecation150#=============================================================================151def deprecated_function(msg=None, deprecated=None, removed=None, updoc=True,152                        replacement=None, _is_method=False,153                        func_module=None):154    """decorator to deprecate a function.155 156    :arg msg: optional msg, default chosen if omitted157    :kwd deprecated: version when function was first deprecated158    :kwd removed: version when function will be removed159    :kwd replacement: alternate name / instructions for replacing this function.160    :kwd updoc: add notice to docstring (default ``True``)161    """162    if msg is None:163        if _is_method:164            msg = "the method %(mod)s.%(klass)s.%(name)s() is deprecated"165        else:166            msg = "the function %(mod)s.%(name)s() is deprecated"167        if deprecated:168            msg += " as of Passlib %(deprecated)s"169        if removed:170            msg += ", and will be removed in Passlib %(removed)s"171        if replacement:172            msg += ", use %s instead" % replacement173        msg += "."174    def build(func):175        is_classmethod = _is_method and isinstance(func, classmethod)176        if is_classmethod:177            # NOTE: PY26 doesn't support "classmethod().__func__" directly...178            func = func.__get__(None, type).__func__179        opts = dict(180            mod=func_module or func.__module__,181            name=func.__name__,182            deprecated=deprecated,183            removed=removed,184            )185        if _is_method:186            def wrapper(*args, **kwds):187                tmp = opts.copy()188                klass = args[0] if is_classmethod else args[0].__class__189                tmp.update(klass=klass.__name__, mod=klass.__module__)190                warn(msg % tmp, DeprecationWarning, stacklevel=2)191                return func(*args, **kwds)192        else:193            text = msg % opts194            def wrapper(*args, **kwds):195                warn(text, DeprecationWarning, stacklevel=2)196                return func(*args, **kwds)197        update_wrapper(wrapper, func)198        if updoc and (deprecated or removed) and \199                   wrapper.__doc__ and ".. deprecated::" not in wrapper.__doc__:200            txt = deprecated or ''201            if removed or replacement:202                txt += "\n    "203                if removed:204                    txt += "and will be removed in version %s" % (removed,)205                if replacement:206                    if removed:207                        txt += ", "208                    txt += "use %s instead" % replacement209                txt += "."210            if not wrapper.__doc__.strip(" ").endswith("\n"):211                wrapper.__doc__ += "\n"212            wrapper.__doc__ += "\n.. deprecated:: %s\n" % (txt,)213        if is_classmethod:214            wrapper = classmethod(wrapper)215        return wrapper216    return build217 218def deprecated_method(msg=None, deprecated=None, removed=None, updoc=True,219                      replacement=None):220    """decorator to deprecate a method.221 222    :arg msg: optional msg, default chosen if omitted223    :kwd deprecated: version when method was first deprecated224    :kwd removed: version when method will be removed225    :kwd replacement: alternate name / instructions for replacing this method.226    :kwd updoc: add notice to docstring (default ``True``)227    """228    return deprecated_function(msg, deprecated, removed, updoc, replacement,229                               _is_method=True)230 231#=============================================================================232# eof233#=============================================================================234 
codekingpro/portable-devtools · Team Ai