mirror of
https://gitlab.com/MoonTestUse1/AdministrationItDepartmens.git
synced 2025-08-14 00:25:46 +02:00
Initial commit
This commit is contained in:
233
venv/Lib/site-packages/passlib/utils/decor.py
Normal file
233
venv/Lib/site-packages/passlib/utils/decor.py
Normal file
@@ -0,0 +1,233 @@
|
||||
"""
|
||||
passlib.utils.decor -- helper decorators & properties
|
||||
"""
|
||||
#=============================================================================
|
||||
# imports
|
||||
#=============================================================================
|
||||
# core
|
||||
from __future__ import absolute_import, division, print_function
|
||||
import logging
|
||||
log = logging.getLogger(__name__)
|
||||
from functools import wraps, update_wrapper
|
||||
import types
|
||||
from warnings import warn
|
||||
# site
|
||||
# pkg
|
||||
from passlib.utils.compat import PY3
|
||||
# local
|
||||
__all__ = [
|
||||
"classproperty",
|
||||
"hybrid_method",
|
||||
|
||||
"memoize_single_value",
|
||||
"memoized_property",
|
||||
|
||||
"deprecated_function",
|
||||
"deprecated_method",
|
||||
]
|
||||
|
||||
#=============================================================================
|
||||
# class-level decorators
|
||||
#=============================================================================
|
||||
class classproperty(object):
|
||||
"""Function decorator which acts like a combination of classmethod+property (limited to read-only properties)"""
|
||||
|
||||
def __init__(self, func):
|
||||
self.im_func = func
|
||||
|
||||
def __get__(self, obj, cls):
|
||||
return self.im_func(cls)
|
||||
|
||||
@property
|
||||
def __func__(self):
|
||||
"""py3 compatible alias"""
|
||||
return self.im_func
|
||||
|
||||
class hybrid_method(object):
|
||||
"""
|
||||
decorator which invokes function with class if called as class method,
|
||||
and with object if called at instance level.
|
||||
"""
|
||||
|
||||
def __init__(self, func):
|
||||
self.func = func
|
||||
update_wrapper(self, func)
|
||||
|
||||
def __get__(self, obj, cls):
|
||||
if obj is None:
|
||||
obj = cls
|
||||
if PY3:
|
||||
return types.MethodType(self.func, obj)
|
||||
else:
|
||||
return types.MethodType(self.func, obj, cls)
|
||||
|
||||
#=============================================================================
|
||||
# memoization
|
||||
#=============================================================================
|
||||
|
||||
def memoize_single_value(func):
|
||||
"""
|
||||
decorator for function which takes no args,
|
||||
and memoizes result. exposes a ``.clear_cache`` method
|
||||
to clear the cached value.
|
||||
"""
|
||||
cache = {}
|
||||
|
||||
@wraps(func)
|
||||
def wrapper():
|
||||
try:
|
||||
return cache[True]
|
||||
except KeyError:
|
||||
pass
|
||||
value = cache[True] = func()
|
||||
return value
|
||||
|
||||
def clear_cache():
|
||||
cache.pop(True, None)
|
||||
wrapper.clear_cache = clear_cache
|
||||
|
||||
return wrapper
|
||||
|
||||
class memoized_property(object):
|
||||
"""
|
||||
decorator which invokes method once, then replaces attr with result
|
||||
"""
|
||||
def __init__(self, func):
|
||||
self.__func__ = func
|
||||
self.__name__ = func.__name__
|
||||
self.__doc__ = func.__doc__
|
||||
|
||||
def __get__(self, obj, cls):
|
||||
if obj is None:
|
||||
return self
|
||||
value = self.__func__(obj)
|
||||
setattr(obj, self.__name__, value)
|
||||
return value
|
||||
|
||||
if not PY3:
|
||||
|
||||
@property
|
||||
def im_func(self):
|
||||
"""py2 alias"""
|
||||
return self.__func__
|
||||
|
||||
def clear_cache(self, obj):
|
||||
"""
|
||||
class-level helper to clear stored value (if any).
|
||||
|
||||
usage: :samp:`type(self).{attr}.clear_cache(self)`
|
||||
"""
|
||||
obj.__dict__.pop(self.__name__, None)
|
||||
|
||||
def peek_cache(self, obj, default=None):
|
||||
"""
|
||||
class-level helper to peek at stored value
|
||||
|
||||
usage: :samp:`value = type(self).{attr}.clear_cache(self)`
|
||||
"""
|
||||
return obj.__dict__.get(self.__name__, default)
|
||||
|
||||
# works but not used
|
||||
##class memoized_class_property(object):
|
||||
## """function decorator which calls function as classmethod,
|
||||
## and replaces itself with result for current and all future invocations.
|
||||
## """
|
||||
## def __init__(self, func):
|
||||
## self.im_func = func
|
||||
##
|
||||
## def __get__(self, obj, cls):
|
||||
## func = self.im_func
|
||||
## value = func(cls)
|
||||
## setattr(cls, func.__name__, value)
|
||||
## return value
|
||||
##
|
||||
## @property
|
||||
## def __func__(self):
|
||||
## "py3 compatible alias"
|
||||
|
||||
#=============================================================================
|
||||
# deprecation
|
||||
#=============================================================================
|
||||
def deprecated_function(msg=None, deprecated=None, removed=None, updoc=True,
|
||||
replacement=None, _is_method=False,
|
||||
func_module=None):
|
||||
"""decorator to deprecate a function.
|
||||
|
||||
:arg msg: optional msg, default chosen if omitted
|
||||
:kwd deprecated: version when function was first deprecated
|
||||
:kwd removed: version when function will be removed
|
||||
:kwd replacement: alternate name / instructions for replacing this function.
|
||||
:kwd updoc: add notice to docstring (default ``True``)
|
||||
"""
|
||||
if msg is None:
|
||||
if _is_method:
|
||||
msg = "the method %(mod)s.%(klass)s.%(name)s() is deprecated"
|
||||
else:
|
||||
msg = "the function %(mod)s.%(name)s() is deprecated"
|
||||
if deprecated:
|
||||
msg += " as of Passlib %(deprecated)s"
|
||||
if removed:
|
||||
msg += ", and will be removed in Passlib %(removed)s"
|
||||
if replacement:
|
||||
msg += ", use %s instead" % replacement
|
||||
msg += "."
|
||||
def build(func):
|
||||
is_classmethod = _is_method and isinstance(func, classmethod)
|
||||
if is_classmethod:
|
||||
# NOTE: PY26 doesn't support "classmethod().__func__" directly...
|
||||
func = func.__get__(None, type).__func__
|
||||
opts = dict(
|
||||
mod=func_module or func.__module__,
|
||||
name=func.__name__,
|
||||
deprecated=deprecated,
|
||||
removed=removed,
|
||||
)
|
||||
if _is_method:
|
||||
def wrapper(*args, **kwds):
|
||||
tmp = opts.copy()
|
||||
klass = args[0] if is_classmethod else args[0].__class__
|
||||
tmp.update(klass=klass.__name__, mod=klass.__module__)
|
||||
warn(msg % tmp, DeprecationWarning, stacklevel=2)
|
||||
return func(*args, **kwds)
|
||||
else:
|
||||
text = msg % opts
|
||||
def wrapper(*args, **kwds):
|
||||
warn(text, DeprecationWarning, stacklevel=2)
|
||||
return func(*args, **kwds)
|
||||
update_wrapper(wrapper, func)
|
||||
if updoc and (deprecated or removed) and \
|
||||
wrapper.__doc__ and ".. deprecated::" not in wrapper.__doc__:
|
||||
txt = deprecated or ''
|
||||
if removed or replacement:
|
||||
txt += "\n "
|
||||
if removed:
|
||||
txt += "and will be removed in version %s" % (removed,)
|
||||
if replacement:
|
||||
if removed:
|
||||
txt += ", "
|
||||
txt += "use %s instead" % replacement
|
||||
txt += "."
|
||||
if not wrapper.__doc__.strip(" ").endswith("\n"):
|
||||
wrapper.__doc__ += "\n"
|
||||
wrapper.__doc__ += "\n.. deprecated:: %s\n" % (txt,)
|
||||
if is_classmethod:
|
||||
wrapper = classmethod(wrapper)
|
||||
return wrapper
|
||||
return build
|
||||
|
||||
def deprecated_method(msg=None, deprecated=None, removed=None, updoc=True,
|
||||
replacement=None):
|
||||
"""decorator to deprecate a method.
|
||||
|
||||
:arg msg: optional msg, default chosen if omitted
|
||||
:kwd deprecated: version when method was first deprecated
|
||||
:kwd removed: version when method will be removed
|
||||
:kwd replacement: alternate name / instructions for replacing this method.
|
||||
:kwd updoc: add notice to docstring (default ``True``)
|
||||
"""
|
||||
return deprecated_function(msg, deprecated, removed, updoc, replacement,
|
||||
_is_method=True)
|
||||
|
||||
#=============================================================================
|
||||
# eof
|
||||
#=============================================================================
|
Reference in New Issue
Block a user