1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 from collections import deque
22 from weakref import WeakValueDictionary
23 import gc
24
26 """Caching dictionary like object that discards the least recently
27 used objects when number of cached items exceeds maxsize.
28
29 cullsize is the fraction of items that will be discarded when
30 maxsize is reached.
31 """
32
33 - def __init__(self, maxsize, cullsize=2, *args, **kwargs):
34 self.cullsize = max(2, cullsize)
35 self.maxsize = max(cullsize, maxsize)
36 self.queue = deque()
37 WeakValueDictionary.__init__(self, *args, **kwargs)
38
40 """free memory by deleting old items from cache"""
41
42
43
44
45
46
47
48
49 while len(self) >= self.maxsize <= len(self.queue):
50 cullsize = max(int(len(self.queue) / self.cullsize), 2)
51 try:
52 for i in range(cullsize):
53 self.queue.popleft()
54 except IndexError:
55
56
57 break
58
59
60
61
62 for i in xrange(5):
63 gc.collect()
64
66
67 while len(self.queue) and self.queue[0][0] == key:
68
69
70 self.queue.popleft()
71
72 while len(self.queue) and self.queue[-1][0] == key:
73
74
75 self.queue.pop()
76
77 if len(self) >= self.maxsize:
78 self.cull()
79
80 self.queue.append((key, value))
81 WeakValueDictionary.__setitem__(self, key, value)
82
84 value = WeakValueDictionary.__getitem__(self, key)
85
86 while len(self.queue) > 0 and self.queue[0][0] == key:
87
88
89 self.queue.popleft()
90
91
92 if not (len(self.queue) and self.queue[-1][0] == key):
93 self.queue.append((key, value))
94
95 return value
96
98
99
100 while len(self.queue) and self.queue[0][0] == key:
101
102
103 self.queue.popleft()
104
105 while len(self.queue) and self.queue[-1][0] == key:
106
107
108 self.queue.pop()
109
110 return WeakValueDictionary.__delitem__(self, key)
111
113 self.queue.clear()
114 return WeakValueDictionary.clear(self)
115
117 if key not in self:
118 self[key] = default
119
120 return self[key]
121