55 lines
		
	
	
	
		
			1.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			55 lines
		
	
	
	
		
			1.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| from datetime import datetime
 | |
| 
 | |
| class ExpiresEntry(object):
 | |
|   """ A single entry under a ExpiresDict. """
 | |
|   def __init__(self, value, expires=None):
 | |
|     self.value = value
 | |
|     self._expiration = expires
 | |
| 
 | |
|   @property
 | |
|   def expired(self):
 | |
|     if self._expiration is None:
 | |
|       return False
 | |
| 
 | |
|     return datetime.now() >= self._expiration
 | |
| 
 | |
| 
 | |
| class ExpiresDict(object):
 | |
|   """ ExpiresDict defines a dictionary-like class whose keys have expiration. The rebuilder is
 | |
|       a function that returns the full contents of the cached dictionary as a dict of the keys
 | |
|       and whose values are TTLEntry's.
 | |
|   """
 | |
|   def __init__(self, rebuilder):
 | |
|     self._rebuilder = rebuilder
 | |
|     self._items = {}
 | |
| 
 | |
|   def __getitem__(self, key):
 | |
|     found = self.get(key)
 | |
|     if found is None:
 | |
|       raise KeyError
 | |
| 
 | |
|     return found
 | |
| 
 | |
|   def get(self, key, default_value=None):
 | |
|     # Check the cache first. If the key is found and it has not yet expired,
 | |
|     # return it.
 | |
|     found = self._items.get(key)
 | |
|     if found is not None and not found.expired:
 | |
|       return found.value
 | |
| 
 | |
|     # Otherwise the key has expired or was not found. Rebuild the cache and check it again.
 | |
|     self._rebuild()
 | |
|     found = self._items.get(key)
 | |
|     if found is None:
 | |
|       return default_value
 | |
| 
 | |
|     return found.value
 | |
| 
 | |
|   def __contains__(self, key):
 | |
|     return self.get(key) is not None
 | |
| 
 | |
|   def _rebuild(self):
 | |
|     self._items = self._rebuilder()
 | |
| 
 | |
|   def set(self, key, value, expires=None):
 | |
|     self._items[key] = ExpiresEntry(value, expires=expires)
 |