1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 """Dictionary with item expiration."""
19
20 __docformat__="restructuredtext en"
21
22 import time
23 import threading
24
25 __all__ = ['ExpiringDictionary']
26
27 sentinel = object()
28
30 """An extension to standard Python dictionary objects which implements item
31 expiration.
32
33 Each item in ExpiringDictionary has its expiration time assigned, after
34 which the item is removed from the mapping.
35
36 :Ivariables:
37 - `_timeouts`: a dictionary with timeout values and timeout callback for
38 stored objects.
39 - `_default_timeout`: the default timeout value (in seconds from now).
40 - `_lock`: access synchronization lock.
41 :Types:
42 - `_timeouts`: `dict`
43 - `_default_timeout`: `int`
44 - `_lock`: `threading.RLock`"""
45
46 __slots__=['_timeouts','_default_timeout','_lock']
47
49 """Initialize an `ExpiringDictionary` object.
50
51 :Parameters:
52 - `default_timeout`: default timeout value for stored objects.
53 :Types:
54 - `default_timeout`: `int`"""
55 dict.__init__(self)
56 self._timeouts={}
57 self._default_timeout=default_timeout
58 self._lock=threading.RLock()
59
67
75
77 self._lock.acquire()
78 try:
79 self._expire_item(key)
80 del self._timeouts[key]
81 if default is not sentinel:
82 return dict.pop(self,key,default)
83 else:
84 return dict.pop(self,key)
85 finally:
86 self._lock.release()
87
90
91 - def set_item(self,key,value,timeout=None,timeout_callback=None):
92 """Set item of the dictionary.
93
94 :Parameters:
95 - `key`: the key.
96 - `value`: the object to store.
97 - `timeout`: timeout value for the object (in seconds from now).
98 - `timeout_callback`: function to be called when the item expires.
99 The callback should accept none, one (the key) or two (the key
100 and the value) arguments.
101 :Types:
102 - `key`: any hashable value
103 - `value`: any python object
104 - `timeout`: `int`
105 - `timeout_callback`: callable"""
106 self._lock.acquire()
107 try:
108 if not timeout:
109 timeout=self._default_timeout
110 self._timeouts[key]=(time.time()+timeout,timeout_callback)
111 return dict.__setitem__(self,key,value)
112 finally:
113 self._lock.release()
114
116 """Do the expiration of dictionary items.
117
118 Remove items that expired by now from the dictionary."""
119 self._lock.acquire()
120 try:
121 for k in self._timeouts.keys():
122 self._expire_item(k)
123 finally:
124 self._lock.release()
125
127 """Do the expiration of a dictionary item.
128
129 Remove the item if it has expired by now.
130
131 :Parameters:
132 - `key`: key to the object.
133 :Types:
134 - `key`: any hashable value"""
135 (timeout,callback)=self._timeouts[key]
136 if timeout<=time.time():
137 item = dict.pop(self, key)
138 del self._timeouts[key]
139 if callback:
140 try:
141 callback(key,item)
142 except TypeError:
143 try:
144 callback(key)
145 except TypeError:
146 callback()
147
148
149