#!/usr/bin/env python # -*- coding: utf-8 -*- """class for caching objects with timed expiry""" # Copyright 2002, 2003 St James Software # # This file is part of jToolkit. # # jToolkit is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # jToolkit is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with jToolkit; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA from jToolkit.data import dates class timecache(dict): """caches objects, remembers time, and dumps when neccessary...""" def __init__(self, expiryperiod): """constructs a timecache dictionary with an expiryperiod given in seconds...""" dict.__init__(self) self.expiryperiod = dates.seconds(expiryperiod) def expired(self, timestamp): """checks if self.timestamp is older than self.expiryperiod""" return timestamp < self.gettimestamp() - self.expiryperiod def expire(self, key): """expires the key, removing the associated item""" self.__delitem__(key) def gettimestamp(self): """returns a new timestamp for the current time...""" return dates.currentdate() def purge(self): """removes all items that are older then self.expiryperiod""" keystodelete = [] for key, (timestamp, value) in dict.iteritems(self): if self.expired(timestamp): keystodelete.append(key) for key in keystodelete: self.expire(key) def __contains__(self, key): """in operator""" if dict.__contains__(self, key): timestamp, value = dict.__getitem__(self, key) if self.expired(timestamp): self.expire(key) # this allows expire to actually reset the value return dict.__contains__(self, key) return 1 return 0 def __getitem__(self, key): """[] access of items""" timestamp, value = dict.__getitem__(self, key) if self.expired(timestamp): self.expire(key) # this allows expire to actually reset the value if dict.__contains__(self, key): return dict.__getitem__(self, key)[1] raise KeyError, key return value def __iter__(self): """iterator access of items""" self.purge() return dict.__iter__(self) def __repr__(self): """x.__repr__() <==> repr(x)""" self.purge() return repr(dict(self.items())) def __setitem__(self, key, value): """[] setting of items""" timestamp = self.gettimestamp() dict.__setitem__(self, key, (timestamp, value)) def has_key(self, key): """check if key is present""" return self.__contains__(key) def get(self, key, default=None): """D.get(k[,d]) -> D[k] if D.has_key(k), else d. d defaults to None.""" timestamp, value = dict.get(self, key, (None, default)) if timestamp is None: return value elif self.expired(timestamp): self.expire(key) # this allows expire to actually reset the value return dict.get(self, key, (None, default))[1] return value def items(self): """D.items() -> list of D's (key, value) pairs, as 2-tuples""" self.purge() return [(key, value) for (key, (timestamp, value)) in dict.items(self)] def iteritems(self): """D.iteritems() -> an iterator over the (key, value) items of D""" self.purge() for key, (timestamp, value) in dict.iteritems(self): yield (key, value) def iterkeys(self): """D.iterkeys() -> an iterator over the keys of D""" self.purge() return dict.iterkeys(self) def itervalues(self): """D.itervalues() -> an iterator over the values of D""" self.purge() for timestamp, value in dict.itervalues(self): yield value def keys(self): """D.keys() -> list of D's keys""" self.purge() return dict.keys(self) def values(self): """D.values() -> list of D's values""" self.purge() return [value for (timestamp, value) in dict.values(self)] def popitem(self): """D.popitem() -> (k, v), remove and return some (key, value) pair as a 2-tuple; but raise KeyError if D is empty""" self.purge() key, (timestamp, value) = dict.popitem(self) return (key, value) def setdefault(self, key, failobj=None): """D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D""" newtimestamp = self.gettimestamp() oldtimestamp, value = dict.setdefault(self, key, (newtimestamp, failobj)) if self.expired(oldtimestamp): dict.__setitem__(self, key, (newtimestamp, failobj)) return failobj return value def update(self, updatedict): """D.update(E) -> None. Update D from E: for k in E.keys(): D[k] = E[k]""" for key in updatedict.keys(): self[key] = updatedict[key]