cache.py PEP8 enhancement
This commit is contained in:
1 parent
060aeff867
commit
58a8ba067c
1 file changed
+17
-30
+17
-30
@@ -54,6 +54,7 @@ try:
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
HAVE_PSUTIL = False
|
HAVE_PSUTIL = False
|
||||||
|
|
||||||
|
|
||||||
def remove_oldest_entries(storage, percentage=90):
|
def remove_oldest_entries(storage, percentage=90):
|
||||||
# compute current memory usage (%)
|
# compute current memory usage (%)
|
||||||
old_mem = psutil.virtual_memory().percent
|
old_mem = psutil.virtual_memory().percent
|
||||||
@@ -66,7 +67,8 @@ def remove_oldest_entries(storage, percentage=90):
|
|||||||
# comute used memory again
|
# comute used memory again
|
||||||
new_mem = psutil.virtual_memory().percent
|
new_mem = psutil.virtual_memory().percent
|
||||||
# if the used memory did not decrease stop
|
# if the used memory did not decrease stop
|
||||||
if new_mem >= old_mem: break
|
if new_mem >= old_mem:
|
||||||
|
break
|
||||||
# net new measurement for memory usage and loop
|
# net new measurement for memory usage and loop
|
||||||
old_mem = new_mem
|
old_mem = new_mem
|
||||||
|
|
||||||
@@ -78,6 +80,7 @@ __all__ = ['Cache', 'lazy_cache']
|
|||||||
|
|
||||||
DEFAULT_TIME_EXPIRE = 300
|
DEFAULT_TIME_EXPIRE = 300
|
||||||
|
|
||||||
|
|
||||||
class CacheAbstract(object):
|
class CacheAbstract(object):
|
||||||
"""
|
"""
|
||||||
Abstract class for cache implementations.
|
Abstract class for cache implementations.
|
||||||
@@ -182,13 +185,14 @@ class CacheInRam(CacheAbstract):
|
|||||||
self.request = request
|
self.request = request
|
||||||
self.storage = OrderedDict() if HAVE_PSUTIL else {}
|
self.storage = OrderedDict() if HAVE_PSUTIL else {}
|
||||||
self.app = request.application if request else ''
|
self.app = request.application if request else ''
|
||||||
|
|
||||||
def initialize(self):
|
def initialize(self):
|
||||||
if self.initialized:
|
if self.initialized:
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
self.initialized = True
|
self.initialized = True
|
||||||
self.locker.acquire()
|
self.locker.acquire()
|
||||||
if not self.app in self.meta_storage:
|
if self.app not in self.meta_storage:
|
||||||
self.storage = self.meta_storage[self.app] = \
|
self.storage = self.meta_storage[self.app] = \
|
||||||
OrderedDict() if HAVE_PSUTIL else {}
|
OrderedDict() if HAVE_PSUTIL else {}
|
||||||
self.stats[self.app] = {'hit_total': 0, 'misses': 0}
|
self.stats[self.app] = {'hit_total': 0, 'misses': 0}
|
||||||
@@ -205,7 +209,7 @@ class CacheInRam(CacheAbstract):
|
|||||||
else:
|
else:
|
||||||
self._clear(storage, regex)
|
self._clear(storage, regex)
|
||||||
|
|
||||||
if not self.app in self.stats:
|
if self.app not in self.stats:
|
||||||
self.stats[self.app] = {'hit_total': 0, 'misses': 0}
|
self.stats[self.app] = {'hit_total': 0, 'misses': 0}
|
||||||
|
|
||||||
self.locker.release()
|
self.locker.release()
|
||||||
@@ -251,7 +255,7 @@ class CacheInRam(CacheAbstract):
|
|||||||
self.locker.acquire()
|
self.locker.acquire()
|
||||||
self.storage[key] = (now, value)
|
self.storage[key] = (now, value)
|
||||||
self.stats[self.app]['misses'] += 1
|
self.stats[self.app]['misses'] += 1
|
||||||
if HAVE_PSUTIL and self.max_ram_utilization!=None and random.random()<0.10:
|
if HAVE_PSUTIL and self.max_ram_utilization is not None and random.random() < 0.10:
|
||||||
remove_oldest_entries(self.storage, percentage=self.max_ram_utilization)
|
remove_oldest_entries(self.storage, percentage=self.max_ram_utilization)
|
||||||
self.locker.release()
|
self.locker.release()
|
||||||
return value
|
return value
|
||||||
@@ -292,14 +296,15 @@ class CacheOnDisk(CacheAbstract):
|
|||||||
self.folder = folder
|
self.folder = folder
|
||||||
self.key_filter_in = lambda key: key
|
self.key_filter_in = lambda key: key
|
||||||
self.key_filter_out = lambda key: key
|
self.key_filter_out = lambda key: key
|
||||||
self.file_lock_time_wait = file_lock_time_wait # How long we should wait before retrying to lock a file held by another process
|
self.file_lock_time_wait = file_lock_time_wait
|
||||||
|
# How long we should wait before retrying to lock a file held by another process
|
||||||
# We still need a mutex for each file as portalocker only blocks other processes
|
# We still need a mutex for each file as portalocker only blocks other processes
|
||||||
self.file_locks = defaultdict(thread.allocate_lock)
|
self.file_locks = defaultdict(thread.allocate_lock)
|
||||||
|
|
||||||
|
|
||||||
# Make sure we use valid filenames.
|
# Make sure we use valid filenames.
|
||||||
if sys.platform == "win32":
|
if sys.platform == "win32":
|
||||||
import base64
|
import base64
|
||||||
|
|
||||||
def key_filter_in_windows(key):
|
def key_filter_in_windows(key):
|
||||||
"""
|
"""
|
||||||
Windows doesn't allow \ / : * ? "< > | in filenames.
|
Windows doesn't allow \ / : * ? "< > | in filenames.
|
||||||
@@ -316,7 +321,6 @@ class CacheOnDisk(CacheAbstract):
|
|||||||
self.key_filter_in = key_filter_in_windows
|
self.key_filter_in = key_filter_in_windows
|
||||||
self.key_filter_out = key_filter_out_windows
|
self.key_filter_out = key_filter_out_windows
|
||||||
|
|
||||||
|
|
||||||
def wait_portalock(self, val_file):
|
def wait_portalock(self, val_file):
|
||||||
"""
|
"""
|
||||||
Wait for the process file lock.
|
Wait for the process file lock.
|
||||||
@@ -328,15 +332,12 @@ class CacheOnDisk(CacheAbstract):
|
|||||||
except:
|
except:
|
||||||
time.sleep(self.file_lock_time_wait)
|
time.sleep(self.file_lock_time_wait)
|
||||||
|
|
||||||
|
|
||||||
def acquire(self, key):
|
def acquire(self, key):
|
||||||
self.file_locks[key].acquire()
|
self.file_locks[key].acquire()
|
||||||
|
|
||||||
|
|
||||||
def release(self, key):
|
def release(self, key):
|
||||||
self.file_locks[key].release()
|
self.file_locks[key].release()
|
||||||
|
|
||||||
|
|
||||||
def __setitem__(self, key, value):
|
def __setitem__(self, key, value):
|
||||||
key = self.key_filter_in(key)
|
key = self.key_filter_in(key)
|
||||||
val_file = recfile.open(key, mode='wb', path=self.folder)
|
val_file = recfile.open(key, mode='wb', path=self.folder)
|
||||||
@@ -344,7 +345,6 @@ class CacheOnDisk(CacheAbstract):
|
|||||||
pickle.dump(value, val_file, pickle.HIGHEST_PROTOCOL)
|
pickle.dump(value, val_file, pickle.HIGHEST_PROTOCOL)
|
||||||
val_file.close()
|
val_file.close()
|
||||||
|
|
||||||
|
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
key = self.key_filter_in(key)
|
key = self.key_filter_in(key)
|
||||||
try:
|
try:
|
||||||
@@ -357,12 +357,10 @@ class CacheOnDisk(CacheAbstract):
|
|||||||
val_file.close()
|
val_file.close()
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
def __contains__(self, key):
|
def __contains__(self, key):
|
||||||
key = self.key_filter_in(key)
|
key = self.key_filter_in(key)
|
||||||
return (key in self.file_locks) or recfile.exists(key, path=self.folder)
|
return (key in self.file_locks) or recfile.exists(key, path=self.folder)
|
||||||
|
|
||||||
|
|
||||||
def __delitem__(self, key):
|
def __delitem__(self, key):
|
||||||
key = self.key_filter_in(key)
|
key = self.key_filter_in(key)
|
||||||
try:
|
try:
|
||||||
@@ -370,13 +368,11 @@ class CacheOnDisk(CacheAbstract):
|
|||||||
except IOError:
|
except IOError:
|
||||||
raise KeyError
|
raise KeyError
|
||||||
|
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
for dirpath, dirnames, filenames in os.walk(self.folder):
|
for dirpath, dirnames, filenames in os.walk(self.folder):
|
||||||
for filename in filenames:
|
for filename in filenames:
|
||||||
yield self.key_filter_out(filename)
|
yield self.key_filter_out(filename)
|
||||||
|
|
||||||
|
|
||||||
def safe_apply(self, key, function, default_value=None):
|
def safe_apply(self, key, function, default_value=None):
|
||||||
"""
|
"""
|
||||||
Safely apply a function to the value of a key in storage and set
|
Safely apply a function to the value of a key in storage and set
|
||||||
@@ -403,25 +399,21 @@ class CacheOnDisk(CacheAbstract):
|
|||||||
val_file.close()
|
val_file.close()
|
||||||
return new_value
|
return new_value
|
||||||
|
|
||||||
|
|
||||||
def keys(self):
|
def keys(self):
|
||||||
return list(self.__iter__())
|
return list(self.__iter__())
|
||||||
|
|
||||||
|
|
||||||
def get(self, key, default=None):
|
def get(self, key, default=None):
|
||||||
try:
|
try:
|
||||||
return self[key]
|
return self[key]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return default
|
return default
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, request=None, folder=None):
|
def __init__(self, request=None, folder=None):
|
||||||
self.initialized = False
|
self.initialized = False
|
||||||
self.request = request
|
self.request = request
|
||||||
self.folder = folder
|
self.folder = folder
|
||||||
self.storage = None
|
self.storage = None
|
||||||
|
|
||||||
|
|
||||||
def initialize(self):
|
def initialize(self):
|
||||||
if self.initialized:
|
if self.initialized:
|
||||||
return
|
return
|
||||||
@@ -440,7 +432,6 @@ class CacheOnDisk(CacheAbstract):
|
|||||||
|
|
||||||
self.storage = CacheOnDisk.PersistentStorage(folder)
|
self.storage = CacheOnDisk.PersistentStorage(folder)
|
||||||
|
|
||||||
|
|
||||||
def __call__(self, key, f,
|
def __call__(self, key, f,
|
||||||
time_expire=DEFAULT_TIME_EXPIRE):
|
time_expire=DEFAULT_TIME_EXPIRE):
|
||||||
self.initialize()
|
self.initialize()
|
||||||
@@ -487,7 +478,6 @@ class CacheOnDisk(CacheAbstract):
|
|||||||
self.storage.release(key)
|
self.storage.release(key)
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
def clear(self, regex=None):
|
def clear(self, regex=None):
|
||||||
self.initialize()
|
self.initialize()
|
||||||
storage = self.storage
|
storage = self.storage
|
||||||
@@ -504,7 +494,6 @@ class CacheOnDisk(CacheAbstract):
|
|||||||
pass
|
pass
|
||||||
storage.release(key)
|
storage.release(key)
|
||||||
|
|
||||||
|
|
||||||
def increment(self, key, value=1):
|
def increment(self, key, value=1):
|
||||||
self.initialize()
|
self.initialize()
|
||||||
self.storage.acquire(key)
|
self.storage.acquire(key)
|
||||||
@@ -513,7 +502,6 @@ class CacheOnDisk(CacheAbstract):
|
|||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class CacheAction(object):
|
class CacheAction(object):
|
||||||
def __init__(self, func, key, time_expire, cache, cache_model):
|
def __init__(self, func, key, time_expire, cache, cache_model):
|
||||||
self.__name__ = func.__name__
|
self.__name__ = func.__name__
|
||||||
@@ -602,6 +590,7 @@ class Cache(object):
|
|||||||
"""
|
"""
|
||||||
from gluon import current
|
from gluon import current
|
||||||
from gluon.http import HTTP
|
from gluon.http import HTTP
|
||||||
|
|
||||||
def wrap(func):
|
def wrap(func):
|
||||||
def wrapped_f():
|
def wrapped_f():
|
||||||
if current.request.env.request_method != 'GET':
|
if current.request.env.request_method != 'GET':
|
||||||
@@ -621,7 +610,8 @@ class Cache(object):
|
|||||||
cache_control = 'max-age=%(time_expire)s, s-maxage=%(time_expire)s' % dict(time_expire=time_expire)
|
cache_control = 'max-age=%(time_expire)s, s-maxage=%(time_expire)s' % dict(time_expire=time_expire)
|
||||||
if not session_ and public_:
|
if not session_ and public_:
|
||||||
cache_control += ', public'
|
cache_control += ', public'
|
||||||
expires = (current.request.utcnow + datetime.timedelta(seconds=time_expire)).strftime('%a, %d %b %Y %H:%M:%S GMT')
|
expires = (current.request.utcnow + datetime.timedelta(seconds=time_expire)
|
||||||
|
).strftime('%a, %d %b %Y %H:%M:%S GMT')
|
||||||
else:
|
else:
|
||||||
cache_control += ', private'
|
cache_control += ', private'
|
||||||
expires = 'Fri, 01 Jan 1990 00:00:00 GMT'
|
expires = 'Fri, 01 Jan 1990 00:00:00 GMT'
|
||||||
@@ -675,11 +665,9 @@ class Cache(object):
|
|||||||
if str(status)[0] in '123':
|
if str(status)[0] in '123':
|
||||||
send_headers = True
|
send_headers = True
|
||||||
if send_headers:
|
if send_headers:
|
||||||
headers = {
|
headers = {'Pragma': None,
|
||||||
'Pragma' : None,
|
|
||||||
'Expires': expires,
|
'Expires': expires,
|
||||||
'Cache-Control' : cache_control
|
'Cache-Control': cache_control}
|
||||||
}
|
|
||||||
current.response.headers.update(headers)
|
current.response.headers.update(headers)
|
||||||
if cache_model and not send_headers:
|
if cache_model and not send_headers:
|
||||||
# we cached already the value, but the status is not valid
|
# we cached already the value, but the status is not valid
|
||||||
@@ -740,8 +728,7 @@ class Cache(object):
|
|||||||
allow replacing cache.ram with cache.with_prefix(cache.ram,'prefix')
|
allow replacing cache.ram with cache.with_prefix(cache.ram,'prefix')
|
||||||
it will add prefix to all the cache keys used.
|
it will add prefix to all the cache keys used.
|
||||||
"""
|
"""
|
||||||
return lambda key, f, time_expire=DEFAULT_TIME_EXPIRE, prefix=prefix:\
|
return lambda key, f, time_expire=DEFAULT_TIME_EXPIRE, prefix=prefix: cache_model(prefix + key, f, time_expire)
|
||||||
cache_model(prefix + key, f, time_expire)
|
|
||||||
|
|
||||||
|
|
||||||
def lazy_cache(key=None, time_expire=None, cache_model='ram'):
|
def lazy_cache(key=None, time_expire=None, cache_model='ram'):
|
||||||
|
|||||||
Reference in new issue
Block a user