From 968a41a4094c20bb24fb1a604a44dd9bbc5aed33 Mon Sep 17 00:00:00 2001 From: Jay Hutchinson Date: Tue, 1 Mar 2022 14:09:59 -0600 Subject: Improved comments, removed whitespace, etc. --- pylru.py | 33 +++++++++++++++++++++++++-------- test.py | 16 ---------------- 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/pylru.py b/pylru.py index 67f3d7d..842c7bf 100644 --- a/pylru.py +++ b/pylru.py @@ -2,7 +2,7 @@ # Cache implementaion with a Least Recently Used (LRU) replacement policy and # a basic dictionary interface. -# Copyright (C) 2006-2019 Jay Hutchinson +# Copyright (C) 2006-2022 Jay Hutchinson # This program 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 @@ -46,7 +46,6 @@ class _dlnode(object): class lrucache(object): - def __init__(self, size, callback=None): self.callback = callback @@ -99,7 +98,6 @@ class lrucache(object): return node.value def get(self, key, default=None): - """Get an item - return default (None) if not present""" if key not in self.table: return default @@ -317,11 +315,23 @@ class lrucache(object): yield node node = node.next + # The methods __getstate__() and __setstate__() are used to correctly + # support the copy and pickle modules from the standard library. In + # particular, the doubly linked list trips up the introspection machinery + # used by copy/pickle. def __getstate__(self): + # Copy the instance attributes. d = self.__dict__.copy() + + # Remove those that we need to do by hand. del d['table'] del d['head'] + # Package up the key/value pairs from the doubly linked list into a + # normal list that can be copied/pickled correctly. We put the + # key/value pairs into the list in order, as returned by dli(), from + # most recently to least recently used, so that the copy can be + # restored with the same ordering. elements = [(node.key, node.value) for node in self.dli()] return (d, elements) @@ -329,12 +339,19 @@ class lrucache(object): d = state[0] elements = state[1] + # Restore the instance attributes, except for the table and head. self.__dict__.update(d) + # Rebuild the table and doubly linked list from the simple list of + # key/value pairs in 'elements'. + # The listSize is the size of the original cache. We want this cache + # to have the same size, but we need to reset it temporarily to set up + # table and head correctly, so save a copy of the size. size = self.listSize - # Create an empty hash table. + # Setup a table and double linked list. This is identical to the way + # __init__() does it. self.table = {} self.head = _dlnode() @@ -346,7 +363,10 @@ class lrucache(object): # Now adjust the list to the desired size. self.size(size) - + # Fill the cache with the keys/values. Because inserted items are + # moved to the top of the doubly linked list, we insert the key/value + # pairs in reverse order. This ensures that the order of the doubly + # linked list is identical to the original cache. for key, value in reversed(elements): self[key] = value @@ -390,7 +410,6 @@ class WriteThroughCacheManager(object): return value def get(self, key, default=None): - """Get an item - return default (None) if not present""" try: return self[key] except KeyError: @@ -426,7 +445,6 @@ class WriteThroughCacheManager(object): return self.store.items() - class WriteBackCacheManager(object): def __init__(self, store, size): self.store = store @@ -482,7 +500,6 @@ class WriteBackCacheManager(object): return value def get(self, key, default=None): - """Get an item - return default (None) if not present""" try: return self[key] except KeyError: diff --git a/test.py b/test.py index 7a4842f..6c0e6de 100644 --- a/test.py +++ b/test.py @@ -8,22 +8,18 @@ import random class simplelrucache: def __init__(self, size): - # Initialize the cache as empty. self.cache = [] self.size = size def __contains__(self, key): - for x in self.cache: if x[0] == key: return True return False - def __getitem__(self, key): - for i in range(len(self.cache)): x = self.cache[i] if x[0] == key: @@ -33,9 +29,7 @@ class simplelrucache: raise KeyError - def __setitem__(self, key, value): - for i in range(len(self.cache)): x = self.cache[i] if x[0] == key: @@ -49,9 +43,7 @@ class simplelrucache: self.cache.append([key, value]) - def __delitem__(self, key): - for i in range(len(self.cache)): if self.cache[i][0] == key: del self.cache[i] @@ -67,7 +59,6 @@ class simplelrucache: def test(a, b, c, d, verify): - for i in range(1000): x = random.randint(0, 512) y = random.randint(0, 512) @@ -115,7 +106,6 @@ def testcache(): assert list(zip(a.keys(), a.values())) == q2 assert list(a.keys()) == list(a) - a = lrucache(128) b = simplelrucache(128) verify(a, b) @@ -138,7 +128,6 @@ def testcache(): def wraptest(): - def verify(p, x): assert p == x.store for key, value in x.cache.items(): @@ -159,9 +148,7 @@ def wraptest(): test(p, x, p, x, verify) - def wraptest2(): - def verify(p, x): for key, value in x.store.items(): if key not in x.dirty: @@ -192,7 +179,6 @@ def wraptest2(): assert p == q def wraptest3(): - def verify(p, x): for key, value in x.store.items(): if key not in x.dirty: @@ -224,10 +210,8 @@ def testDecorator(): if __name__ == '__main__': - random.seed() - for i in range(20): testcache() wraptest() -- cgit v1.2.1