Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(239)

Side by Side Diff: third_party/google-endpoints/cachetools/ttl.py

Issue 2666783008: Add google-endpoints to third_party/. (Closed)
Patch Set: Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 import collections
2 import time
3
4 from .cache import Cache
5
6
7 class _Link(object):
8
9 __slots__ = ('key', 'expire', 'next', 'prev')
10
11 def __init__(self, key=None, expire=None):
12 self.key = key
13 self.expire = expire
14
15 def __reduce__(self):
16 return _Link, (self.key, self.expire)
17
18 def unlink(self):
19 next = self.next
20 prev = self.prev
21 prev.next = next
22 next.prev = prev
23
24
25 class _Timer(object):
26
27 def __init__(self, timer):
28 self.__timer = timer
29 self.__nesting = 0
30
31 def __call__(self):
32 if self.__nesting == 0:
33 return self.__timer()
34 else:
35 return self.__time
36
37 def __enter__(self):
38 if self.__nesting == 0:
39 self.__time = time = self.__timer()
40 else:
41 time = self.__time
42 self.__nesting += 1
43 return time
44
45 def __exit__(self, *exc):
46 self.__nesting -= 1
47
48 def __reduce__(self):
49 return _Timer, (self.__timer,)
50
51 def __getattr__(self, name):
52 return getattr(self.__timer, name)
53
54
55 class TTLCache(Cache):
56 """LRU Cache implementation with per-item time-to-live (TTL) value."""
57
58 def __init__(self, maxsize, ttl, timer=time.time, missing=None,
59 getsizeof=None):
60 Cache.__init__(self, maxsize, missing, getsizeof)
61 self.__root = root = _Link()
62 root.prev = root.next = root
63 self.__links = collections.OrderedDict()
64 self.__timer = _Timer(timer)
65 self.__ttl = ttl
66
67 def __contains__(self, key):
68 try:
69 link = self.__links[key] # no reordering
70 except KeyError:
71 return False
72 else:
73 return not (link.expire < self.__timer())
74
75 def __getitem__(self, key, cache_getitem=Cache.__getitem__):
76 try:
77 link = self.__getlink(key)
78 except KeyError:
79 expired = False
80 else:
81 expired = link.expire < self.__timer()
82 if expired:
83 return self.__missing__(key)
84 else:
85 return cache_getitem(self, key)
86
87 def __setitem__(self, key, value, cache_setitem=Cache.__setitem__):
88 with self.__timer as time:
89 self.expire(time)
90 cache_setitem(self, key, value)
91 try:
92 link = self.__getlink(key)
93 except KeyError:
94 self.__links[key] = link = _Link(key)
95 else:
96 link.unlink()
97 link.expire = time + self.__ttl
98 link.next = root = self.__root
99 link.prev = prev = root.prev
100 prev.next = root.prev = link
101
102 def __delitem__(self, key, cache_delitem=Cache.__delitem__):
103 cache_delitem(self, key)
104 link = self.__links.pop(key)
105 link.unlink()
106 if link.expire < self.__timer():
107 raise KeyError(key)
108
109 def __iter__(self):
110 root = self.__root
111 curr = root.next
112 while curr is not root:
113 # "freeze" time for iterator access
114 with self.__timer as time:
115 if not (curr.expire < time):
116 yield curr.key
117 curr = curr.next
118
119 def __len__(self):
120 root = self.__root
121 curr = root.next
122 time = self.__timer()
123 count = len(self.__links)
124 while curr is not root and curr.expire < time:
125 count -= 1
126 curr = curr.next
127 return count
128
129 def __setstate__(self, state):
130 self.__dict__.update(state)
131 root = self.__root
132 root.prev = root.next = root
133 for link in sorted(self.__links.values(), key=lambda obj: obj.expire):
134 link.next = root
135 link.prev = prev = root.prev
136 prev.next = root.prev = link
137 self.expire(self.__timer())
138
139 def __repr__(self, cache_repr=Cache.__repr__):
140 with self.__timer as time:
141 self.expire(time)
142 return cache_repr(self)
143
144 @property
145 def currsize(self):
146 with self.__timer as time:
147 self.expire(time)
148 return super(TTLCache, self).currsize
149
150 @property
151 def timer(self):
152 """The timer function used by the cache."""
153 return self.__timer
154
155 @property
156 def ttl(self):
157 """The time-to-live value of the cache's items."""
158 return self.__ttl
159
160 def expire(self, time=None):
161 """Remove expired items from the cache."""
162 if time is None:
163 time = self.__timer()
164 root = self.__root
165 curr = root.next
166 links = self.__links
167 cache_delitem = Cache.__delitem__
168 while curr is not root and curr.expire < time:
169 cache_delitem(self, curr.key)
170 del links[curr.key]
171 next = curr.next
172 curr.unlink()
173 curr = next
174
175 def clear(self):
176 with self.__timer as time:
177 self.expire(time)
178 Cache.clear(self)
179
180 def get(self, *args, **kwargs):
181 with self.__timer:
182 return Cache.get(self, *args, **kwargs)
183
184 def pop(self, *args, **kwargs):
185 with self.__timer:
186 return Cache.pop(self, *args, **kwargs)
187
188 def setdefault(self, *args, **kwargs):
189 with self.__timer:
190 return Cache.setdefault(self, *args, **kwargs)
191
192 def popitem(self):
193 """Remove and return the `(key, value)` pair least recently used that
194 has not already expired.
195
196 """
197 with self.__timer as time:
198 self.expire(time)
199 try:
200 key = next(iter(self.__links))
201 except StopIteration:
202 raise KeyError('%s is empty' % self.__class__.__name__)
203 else:
204 return (key, self.pop(key))
205
206 if hasattr(collections.OrderedDict, 'move_to_end'):
207 def __getlink(self, key):
208 value = self.__links[key]
209 self.__links.move_to_end(key)
210 return value
211 else:
212 def __getlink(self, key):
213 value = self.__links.pop(key)
214 self.__links[key] = value
215 return value
OLDNEW
« no previous file with comments | « third_party/google-endpoints/cachetools/rr.py ('k') | third_party/google-endpoints/copyreg/__init__.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698