pyxmpp.expdict

Package pyxmpp :: Module expdict |
[hide private]

# Source Code for Module pyxmpp.expdict

      1  #
      2  # (C) Copyright 2003-2010 Jacek Konieczny <jajcus@jajcus.net>
      3  #
      4  # This program is free software; you can redistribute it and/or modify
      5  # it under the terms of the GNU Lesser General Public License Version
      6  # 2.1 as published by the Free Software Foundation.
      7  #
      8  # This program is distributed in the hope that it will be useful,
      9  # but WITHOUT ANY WARRANTY; without even the implied warranty of
     10  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     11  # GNU Lesser General Public License for more details.
     12  #
     13  # You should have received a copy of the GNU Lesser General Public
     14  # License along with this program; if not, write to the Free Software
     15  # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
     16  #
     17
     18  """Dictionary with item expiration."""
     19
     20  __revision__="$Id: expdict.py 714 2010-04-05 10:20:10Z jajcus $"
     21  __docformat__="restructuredtext en"
     22
     23  import time
     24  import threading
     25
     26  __all__ = ['ExpiringDictionary']
     27
     28  sentinel = object()
     29
     30 -class ExpiringDictionary(dict):
     31      """An extension to standard Python dictionary objects which implements item
     32      expiration.
     33
     34      Each item in ExpiringDictionary has its expiration time assigned, after
     35      which the item is removed from the mapping.
     36
     37      :Ivariables:
     38          - `_timeouts`: a dictionary with timeout values and timeout callback for
     39            stored objects.
     40          - `_default_timeout`: the default timeout value (in seconds from now).
     41          - `_lock`: access synchronization lock.
     42      :Types:
     43          - `_timeouts`: `dict`
     44          - `_default_timeout`: `int`
     45          - `_lock`: `threading.RLock`"""
     46
     47      __slots__=['_timeouts','_default_timeout','_lock']
     48
     49 -    def __init__(self,default_timeout=300):
     50          """Initialize an `ExpiringDictionary` object.
     51
     52          :Parameters:
     53              - `default_timeout`: default timeout value for stored objects.
     54          :Types:
     55              - `default_timeout`: `int`"""
     56          dict.__init__(self)
     57          self._timeouts={}
     58          self._default_timeout=default_timeout
     59          self._lock=threading.RLock()
     60
     61 -    def __delitem__(self,key):
     62          self._lock.acquire()
     63          try:
     64              del self._timeouts[key]
     65              return dict.__delitem__(self,key)
     66          finally:
     67              self._lock.release()
     68
     69 -    def __getitem__(self,key):
     70          self._lock.acquire()
     71          try:
     72              self._expire_item(key)
     73              return dict.__getitem__(self,key)
     74          finally:
     75              self._lock.release()
     76
     77 -    def pop(self,key,default=sentinel):
     78          self._lock.acquire()
     79          try:
     80              self._expire_item(key)
     81              del self._timeouts[key]
     82              if default is not sentinel:
     83                  return dict.pop(self,key,default)
     84              else:
     85                  return dict.pop(self,key)
     86          finally:
     87              self._lock.release()
     88
     89 -    def __setitem__(self,key,value):
     90          return self.set_item(key,value)
     91
     92 -    def set_item(self,key,value,timeout=None,timeout_callback=None):
     93          """Set item of the dictionary.
     94
     95          :Parameters:
     96              - `key`: the key.
     97              - `value`: the object to store.
     98              - `timeout`: timeout value for the object (in seconds from now).
     99              - `timeout_callback`: function to be called when the item expires.
    100                The callback should accept none, one (the key) or two (the key
    101                and the value) arguments.
    102          :Types:
    103              - `key`: any hashable value
    104              - `value`: any python object
    105              - `timeout`: `int`
    106              - `timeout_callback`: callable"""
    107          self._lock.acquire()
    108          try:
    109              if not timeout:
    110                  timeout=self._default_timeout
    111              self._timeouts[key]=(time.time()+timeout,timeout_callback)
    112              return dict.__setitem__(self,key,value)
    113          finally:
    114              self._lock.release()
    115
    116 -    def expire(self):
    117          """Do the expiration of dictionary items.
    118
    119          Remove items that expired by now from the dictionary."""
    120          self._lock.acquire()
    121          try:
    122              for k in self._timeouts.keys():
    123                  self._expire_item(k)
    124          finally:
    125              self._lock.release()
    126
    127 -    def _expire_item(self,key):
    128          """Do the expiration of a dictionary item.
    129
    130          Remove the item if it has expired by now.
    131
    132          :Parameters:
    133              - `key`: key to the object.
    134          :Types:
    135              - `key`: any hashable value"""
    136          (timeout,callback)=self._timeouts[key]
    137          if timeout<=time.time():
    138              item = dict.pop(self, key)
    139              del self._timeouts[key]
    140              if callback:
    141                  try:
    142                      callback(key,item)
    143                  except TypeError:
    144                      try:
    145                          callback(key)
    146                      except TypeError:
    147                          callback()
    148
    149  # vi: sts=4 et sw=4
    150