Source code for dynpy.caching
"""
This module implements several decorates that can help with caching/memoizing
methods and properties.
"""
from __future__ import division, print_function, absolute_import
import six
range = six.moves.range
from collections import OrderedDict
import functools
[docs]
class setup_cached_data_method(object):
"""
Class used to generate memoizing decorators.
"""
def __init__(self, depends_on_attributes=None, sideeffect_attributes=None,
args_dont_use_for_key=None, use_cache_check_func=None):
self.depends_on_attributes = depends_on_attributes
self.sideeffect_attributes = sideeffect_attributes
self.args_dont_use_for_key = args_dont_use_for_key
self.use_cache_check_func = use_cache_check_func
def __call__(self, func):
def wrapper(obj, *args, **kwds):
kwditems = tuple(kwds.items())
if self.args_dont_use_for_key is not None:
kwditems = tuple((k,v) for k, v in kwditems if k not in self.args_dont_use_for_key)
dependattrs = None
if self.depends_on_attributes is not None:
dependattrs = tuple([getattr(obj, depended_attr) for depended_attr in self.depends_on_attributes])
try:
keyEntries = tuple([
func,
args,
kwditems,
dependattrs
])
except TypeError:
print("Can't hash for tuple:")
print(" - func=%s\n - args=%s\n - kwds=%s" %
(str(func), str(args), str(kwds.items())))
if self.depends_on_attributes is not None:
for depended_attr in self.depends_on_attributes:
print(" - attr[%s]=%s" %
(depended_attr, getattr(obj, depended_attr)))
raise
#key = hash(keyEntries)
key = keyEntries
if getattr(obj, '_cache', None) is None:
obj._cache = OrderedDict()
if key not in obj._cache or \
(self.use_cache_check_func is not None and
not self.use_cache_check_func(obj._cache[key], *args, **kwds)):
returnValue = func(obj, *args, **kwds)
sideEffects = None
if self.sideeffect_attributes is not None:
sideEffects = tuple(
[getattr(obj, sideeffect, None)
for sideeffect in self.sideeffect_attributes])
obj._cache[key] = (returnValue, sideEffects)
else:
returnValue, sideEffects = obj._cache[key]
if sideEffects is not None:
for n in range(len(sideEffects)):
setattr(obj, self.sideeffect_attributes[n], sideEffects[n])
return returnValue
return wrapper
[docs]
def cached_data_method(f):
"""
Decorator for caching an object's method
"""
return functools.wraps(f)( setup_cached_data_method()(f) )
[docs]
def cached_data_prop(f):
"""
Decorator for caching an object's property
"""
return property( functools.wraps(f)( cached_data_method(f) ) )