Package translate :: Package misc :: Module lru

[hide private]
[frames] | no frames]

# Source Code for Module translate.misc.lru

      1  #!/usr/bin/env python
      2  # -*- coding: utf-8 -*-
      3  #
      4  # Copyright 2009 Zuza Software Foundation
      5  #
      6  # This file is part of translate.
      7  #
      8  # This program is free software; you can redistribute it and/or modify
      9  # it under the terms of the GNU General Public License as published by
     10  # the Free Software Foundation; either version 2 of the License, or
     11  # (at your option) any later version.
     12  #
     13  # This program is distributed in the hope that it will be useful,
     14  # but WITHOUT ANY WARRANTY; without even the implied warranty of
     15  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16  # GNU General Public License for more details.
     17  #
     18  # You should have received a copy of the GNU General Public License
     19  # along with this program; if not, see <http://www.gnu.org/licenses/>.
     20
     21  from collections import deque
     22  from weakref import WeakValueDictionary
     23  import gc
     24
     25 -class LRUCachingDict(WeakValueDictionary):
     26      """Caching dictionary like object that discards the least recently
     27      used objects when number of cached items exceeds maxsize.
     28
     29      cullsize is the fraction of items that will be discarded when
     30      maxsize is reached.
     31      """
     32
     33 -    def __init__(self, maxsize, cullsize=2, *args, **kwargs):
     34          self.cullsize = max(2, cullsize)
     35          self.maxsize = max(cullsize, maxsize)
     36          self.queue = deque()
     37          WeakValueDictionary.__init__(self, *args, **kwargs)
     38
     39 -    def __setitem__(self, key, value):
     40          # check boundaries to minimiza duplicate references
     41          while len(self.queue) and self.queue[0][0] == key:
     42              # item at left end of queue pop it since it'll be appended
     43              # to right
     44              self.queue.popleft()
     45
     46          while len(self.queue) and self.queue[-1][0] == key:
     47              # item at right end of queue pop it since it'll be
     48              # appended again
     49              self.queue.pop()
     50
     51          self.queue.append((key, value))
     52          WeakValueDictionary.__setitem__(self, key, value)
     53
     54          if len(self) > self.maxsize:
     55              while len(self) > (self.maxsize - self.maxsize / self.cullsize):
     56                  # maximum cache size exceeded, remove an old item
     57                  self.queue.popleft()
     58                  while gc.collect() > 0:
     59                      pass
     60
     61 -    def __getitem__(self, key):
     62          value = WeakValueDictionary.__getitem__(self, key)
     63          # check boundaries to minimiza duplicate references
     64          while len(self.queue) > 1 and self.queue[0][0] == key:
     65              # item at left end of queue pop it since it'll be appended
     66              # to right
     67              self.queue.popleft()
     68
     69          # only append if item is not at right end of queue
     70          if not (len(self.queue) and self.queue[-1][0] == key):
     71              self.queue.append((key, value))
     72
     73          return value
     74
     75 -    def __delitem__(self, key):
     76          # can't efficiently find item in queue to delete, check
     77          # boundaries. otherwise just wait till next cache purge
     78          while len(self.queue) and self.queue[0][0] == key:
     79              # item at left end of queue pop it since it'll be appended
     80              # to right
     81              self.queue.popleft()
     82
     83          while len(self.queue) and self.queue[-1][0] == key:
     84              # item at right end of queue pop it since it'll be
     85              # appended again
     86              self.queue.pop()
     87
     88          return WeakValueDictionary.__delitem__(self, key)
     89
     90 -    def clear(self):
     91          self.queue.clear()
     92          return WeakValueDictionary.clear(self)
     93
     94 -    def setdefault(self, key, default):
     95          if key not in self:
     96              self[key]=default
     97
     98          return self[key]
     99