From adadcd6815ef5c864e22202921922475e420139e Mon Sep 17 00:00:00 2001 From: William McBrine Date: Mon, 22 Dec 2008 21:57:40 -0500 Subject: [PATCH] A BSD-licensed version of lrucache.py. (The copyright notice is the only thing changed.) Finally pyTivo is legal. --- lrucache.py | 51 +++++++++++++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/lrucache.py b/lrucache.py index 7f8752e..ca8733d 100644 --- a/lrucache.py +++ b/lrucache.py @@ -3,6 +3,13 @@ # Copyright 2004 Evan Prodromou # Licensed under the Academic Free License 2.1 +# Licensed for ftputil under the revised BSD license +# with permission by the author, Evan Prodromou. Many +# thanks, Evan! :-) +# +# The original file is available at +# http://pypi.python.org/pypi/lrucache/0.2 . + # arch-tag: LRU cache main module """a simple LRU (Least-Recently-Used) cache module @@ -44,7 +51,7 @@ DEFAULT_SIZE = 16 class CacheKeyError(KeyError): """Error raised when cache requests fail - + When a cache record is accessed which no longer exists (or never did), this error is raised. To avoid it, you may want to check for the existence of a cache record before reading or deleting it.""" @@ -52,35 +59,35 @@ class CacheKeyError(KeyError): class LRUCache(object): """Least-Recently-Used (LRU) cache. - + Instances of this class provide a least-recently-used (LRU) cache. They emulate a Python mapping type. You can use an LRU cache more or less like a Python dictionary, with the exception that objects you put into the cache may be discarded before you take them out. - + Some example usage:: - + cache = LRUCache(32) # new cache cache['foo'] = get_file_contents('foo') # or whatever - + if 'foo' in cache: # if it's still in cache... - # use cached version + # use cached version contents = cache['foo'] else: - # recalculate + # recalculate contents = get_file_contents('foo') - # store in cache for next time + # store in cache for next time cache['foo'] = contents print cache.size # Maximum size - + print len(cache) # 0 <= len(cache) <= cache.size - + cache.size = 10 # Auto-shrink on size assignment - + for i in range(50): # note: larger than cache size cache[i] = i - + if 0 not in cache: print 'Zero was discarded.' if 42 in cache: @@ -89,17 +96,17 @@ class LRUCache(object): for j in cache: # iterate (in LRU order) print j, cache[j] # iterator produces keys, not values """ - + class __Node(object): """Record of a cached value. Not for public consumption.""" - + def __init__(self, key, obj, timestamp): object.__init__(self) self.key = key self.obj = obj self.atime = timestamp self.mtime = self.atime - + def __cmp__(self, other): return cmp(self.atime, other.atime) @@ -114,20 +121,20 @@ class LRUCache(object): raise ValueError, size elif type(size) is not type(0): raise TypeError, size - object.__init__(self) + object.__init__(self) self.__heap = [] self.__dict = {} self.size = size """Maximum size of the cache. If more than 'size' elements are added to the cache, the least-recently-used ones will be discarded.""" - + def __len__(self): return len(self.__heap) - + def __contains__(self, key): return self.__dict.has_key(key) - + def __setitem__(self, key, obj): if self.__dict.has_key(key): node = self.__dict[key] @@ -143,7 +150,7 @@ class LRUCache(object): node = self.__Node(key, obj, time.time()) self.__dict[key] = node heappush(self.__heap, node) - + def __getitem__(self, key): if not self.__dict.has_key(key): raise CacheKeyError(key) @@ -152,7 +159,7 @@ class LRUCache(object): node.atime = time.time() heapify(self.__heap) return node.obj - + def __delitem__(self, key): if not self.__dict.has_key(key): raise CacheKeyError(key) @@ -177,7 +184,7 @@ class LRUCache(object): while len(self.__heap) > value: lru = heappop(self.__heap) del self.__dict[lru.key] - + def __repr__(self): return "<%s (%d elements)>" % (str(self.__class__), len(self.__heap)) -- 2.11.4.GIT