else/Cacheclass/cacheclass.py

64 lines
1.7 KiB
Python
Raw Normal View History

2017-03-30 22:56:01 +00:00
import collections
2017-04-01 07:08:56 +00:00
import itertools
2017-03-30 22:56:01 +00:00
import time
2017-04-01 07:08:56 +00:00
2017-03-30 22:56:01 +00:00
class Cache:
2017-04-01 07:08:56 +00:00
def __init__(self, maxage=None, maxlen=None, shrink_delay=None):
self.maxage = maxage
2017-03-30 22:56:01 +00:00
self.maxlen = maxlen
2017-04-01 07:08:56 +00:00
self.shrink_delay = shrink_delay
self.last_shrink = time.time()
2017-03-30 22:56:01 +00:00
self._dict = {}
self._recency = {}
def __getitem__(self, key):
2017-04-01 07:08:56 +00:00
self._shrink()
2017-03-30 22:56:01 +00:00
value = self._dict[key]
self._maintain(key)
return value
def __setitem__(self, key, value):
self._shrink()
self._dict[key] = value
self._maintain(key)
def _maintain(self, key):
self._recency[key] = time.time()
def _shrink(self):
2017-04-01 07:08:56 +00:00
if self.shrink_delay is not None:
if time.time() - self.last_shrink > self.shrink_delay:
return
2017-03-30 22:56:01 +00:00
2017-04-01 07:08:56 +00:00
now = time.time()
self.last_shrink = now
2017-03-30 22:56:01 +00:00
2017-04-01 07:08:56 +00:00
if self.maxlen is None:
pop_count = 0
else:
pop_count = len(self._dict) - self.maxlen
2017-03-30 22:56:01 +00:00
keys = sorted(self._recency.keys(), key=self._recency.get)
2017-04-01 07:08:56 +00:00
for key in itertools.islice(keys, 0, pop_count):
self.remove(key)
if self.maxage is not None:
for key in itertools.islice(keys, pop_count, None):
last_used = self._recency[key]
age = now - last_used
if age > self.maxage:
self.remove(key)
2017-03-30 22:56:01 +00:00
def get(self, key, fallback=None):
try:
return self[key]
except KeyError:
return fallback
def remove(self, key):
try:
self._dict.pop(key)
self._recency.pop(key)
except KeyError:
return