Package flickrapi :: Module cache
[hide private]
[frames] | no frames]

Source Code for Module flickrapi.cache

  1  # -*- encoding: utf-8 -*- 
  2   
  3  '''Call result cache. 
  4   
  5  Designed to have the same interface as the `Django low-level cache API`_. 
  6  Heavily inspired (read: mostly copied-and-pasted) from the Django framework - 
  7  thanks to those guys for designing a simple and effective cache! 
  8   
  9  .. _`Django low-level cache API`: http://www.djangoproject.com/documentation/cache/#the-low-level-cache-api 
 10  ''' 
 11   
 12  import threading 
 13  import time 
14 15 16 -class SimpleCache(object):
17 '''Simple response cache for FlickrAPI calls. 18 19 This stores max 50 entries, timing them out after 120 seconds: 20 >>> cache = SimpleCache(timeout=120, max_entries=50) 21 ''' 22
23 - def __init__(self, timeout=300, max_entries=200):
24 self.storage = {} 25 self.expire_info = {} 26 self.lock = threading.RLock() 27 self.default_timeout = timeout 28 self.max_entries = max_entries 29 self.cull_frequency = 3
30
31 - def locking(method):
32 '''Method decorator, ensures the method call is locked''' 33 34 def locked(self, *args, **kwargs): 35 self.lock.acquire() 36 try: 37 return method(self, *args, **kwargs) 38 finally: 39 self.lock.release()
40 41 return locked
42 43 @locking
44 - def get(self, key, default=None):
45 '''Fetch a given key from the cache. If the key does not exist, return 46 default, which itself defaults to None. 47 ''' 48 49 now = time.time() 50 exp = self.expire_info.get(key) 51 if exp is None: 52 return default 53 elif exp < now: 54 self.delete(key) 55 return default 56 57 return self.storage[key]
58 59 @locking
60 - def set(self, key, value, timeout=None):
61 '''Set a value in the cache. If timeout is given, that timeout will be 62 used for the key; otherwise the default cache timeout will be used. 63 ''' 64 65 if len(self.storage) >= self.max_entries: 66 self.cull() 67 if timeout is None: 68 timeout = self.default_timeout 69 self.storage[key] = value 70 self.expire_info[key] = time.time() + timeout
71 72 @locking
73 - def delete(self, key):
74 '''Deletes a key from the cache, 75 failing silently if it doesn't exist.''' 76 77 if key in self.storage: 78 del self.storage[key] 79 if key in self.expire_info: 80 del self.expire_info[key]
81 82 @locking
83 - def has_key(self, key):
84 '''Returns True if the key is in the cache and has not expired.''' 85 return self.get(key) is not None
86 87 @locking
88 - def __contains__(self, key):
89 '''Returns True if the key is in the cache and has not expired.''' 90 return self.has_key(key)
91 92 @locking
93 - def cull(self):
94 '''Reduces the number of cached items''' 95 96 doomed = [k for (i, k) in enumerate(self.storage) 97 if i % self.cull_frequency == 0] 98 for k in doomed: 99 self.delete(k)
100 101 @locking
102 - def __len__(self):
103 '''Returns the number of cached items -- they might be expired 104 though. 105 ''' 106 107 return len(self.storage)
108