summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/util.py
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2010-05-31 11:56:08 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2010-05-31 11:56:08 -0400
commitcfe9fadc61cfa05c71255fc0e447360199054ffc (patch)
tree737dfbe4e262202a8a94f9335c558d519f843098 /lib/sqlalchemy/util.py
parentb42d679cf751d3311a45061c78371fc83bb1d5c2 (diff)
downloadsqlalchemy-cfe9fadc61cfa05c71255fc0e447360199054ffc.tar.gz
change the weakkeydict to be just an LRU cache. Add tests
for the "many combinations of UPDATE keys" issue.
Diffstat (limited to 'lib/sqlalchemy/util.py')
-rw-r--r--lib/sqlalchemy/util.py49
1 files changed, 49 insertions, 0 deletions
diff --git a/lib/sqlalchemy/util.py b/lib/sqlalchemy/util.py
index c2c85a4c9..4b04901a1 100644
--- a/lib/sqlalchemy/util.py
+++ b/lib/sqlalchemy/util.py
@@ -19,6 +19,7 @@ except ImportError:
py3k = getattr(sys, 'py3kwarning', False) or sys.version_info >= (3, 0)
jython = sys.platform.startswith('java')
+win32 = sys.platform.startswith('win')
if py3k:
set_types = set
@@ -1542,6 +1543,54 @@ class WeakIdentityMapping(weakref.WeakKeyDictionary):
def _ref(self, object):
return self._keyed_weakref(object, self._cleanup)
+import time
+if win32 or jython:
+ time_func = time.clock
+else:
+ time_func = time.time
+
+class LRUCache(dict):
+ def __init__(self, capacity=100, threshold=.5):
+ self.capacity = capacity
+ self.threshold = threshold
+
+ def __getitem__(self, key):
+ item = dict.__getitem__(self, key)
+ item[2] = time_func()
+ return item[1]
+
+ def values(self):
+ return [i[1] for i in dict.values(self)]
+
+ def setdefault(self, key, value):
+ if key in self:
+ return self[key]
+ else:
+ self[key] = value
+ return value
+
+ def __setitem__(self, key, value):
+ item = dict.get(self, key)
+ if item is None:
+ item = [key, value, time_func()]
+ dict.__setitem__(self, key, item)
+ else:
+ item[1] = value
+ self._manage_size()
+
+ def _manage_size(self):
+ while len(self) > self.capacity + self.capacity * self.threshold:
+ bytime = sorted(dict.values(self),
+ key=operator.itemgetter(2),
+ reverse=True)
+ for item in bytime[self.capacity:]:
+ try:
+ del self[item[0]]
+ except KeyError:
+ # if we couldnt find a key, most
+ # likely some other thread broke in
+ # on us. loop around and try again
+ break
def warn(msg, stacklevel=3):
if isinstance(msg, basestring):