| 
									
										
										
										
											2001-02-01 05:27:45 +00:00
										 |  |  | """Weak reference support for Python.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This module is an implementation of PEP 205: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | http://python.sourceforge.net/peps/pep-0205.html | 
					
						
							|  |  |  | """
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-19 16:26:06 +00:00
										 |  |  | # Naming convention: Variables named "wr" are weak reference objects; | 
					
						
							|  |  |  | # they are called this instead of "ref" to avoid name collisions with | 
					
						
							|  |  |  | # the module-global ref() function imported from _weakref. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-02-01 05:27:45 +00:00
										 |  |  | import UserDict | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | from _weakref import \ | 
					
						
							|  |  |  |      getweakrefcount, \ | 
					
						
							|  |  |  |      getweakrefs, \ | 
					
						
							|  |  |  |      ref, \ | 
					
						
							|  |  |  |      proxy, \ | 
					
						
							|  |  |  |      CallableProxyType, \ | 
					
						
							|  |  |  |      ProxyType, \ | 
					
						
							|  |  |  |      ReferenceType | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-10-05 21:54:09 +00:00
										 |  |  | from exceptions import ReferenceError | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-02-01 05:27:45 +00:00
										 |  |  | ProxyTypes = (ProxyType, CallableProxyType) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-10 19:11:23 +00:00
										 |  |  | __all__ = ["ref", "proxy", "getweakrefcount", "getweakrefs", | 
					
						
							| 
									
										
										
										
											2001-03-01 04:27:19 +00:00
										 |  |  |            "WeakKeyDictionary", "ReferenceType", "ProxyType", | 
					
						
							|  |  |  |            "CallableProxyType", "ProxyTypes", "WeakValueDictionary"] | 
					
						
							| 
									
										
										
										
											2001-02-01 05:27:45 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-19 16:26:06 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-02-27 18:36:56 +00:00
										 |  |  | class WeakValueDictionary(UserDict.UserDict): | 
					
						
							| 
									
										
										
										
											2001-04-19 16:26:06 +00:00
										 |  |  |     """Mapping class that references values weakly.
 | 
					
						
							| 
									
										
										
										
											2001-02-01 05:27:45 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-19 16:26:06 +00:00
										 |  |  |     Entries in the dictionary will be discarded when no strong | 
					
						
							|  |  |  |     reference to the value exists anymore | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2001-02-01 05:27:45 +00:00
										 |  |  |     # We inherit the constructor without worrying about the input | 
					
						
							|  |  |  |     # dictionary; since it uses our .update() method, we get the right | 
					
						
							| 
									
										
										
										
											2001-03-01 03:06:03 +00:00
										 |  |  |     # checks (if the other dictionary is a WeakValueDictionary, | 
					
						
							|  |  |  |     # objects are unwrapped on the way out, and we always wrap on the | 
					
						
							|  |  |  |     # way in). | 
					
						
							| 
									
										
										
										
											2001-02-01 05:27:45 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def __getitem__(self, key): | 
					
						
							| 
									
										
										
										
											2001-08-03 04:11:27 +00:00
										 |  |  |         o = self.data[key]() | 
					
						
							| 
									
										
										
										
											2001-02-01 05:27:45 +00:00
										 |  |  |         if o is None: | 
					
						
							|  |  |  |             raise KeyError, key | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             return o | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __repr__(self): | 
					
						
							| 
									
										
										
										
											2001-03-01 03:06:03 +00:00
										 |  |  |         return "<WeakValueDictionary at %s>" % id(self) | 
					
						
							| 
									
										
										
										
											2001-02-01 05:27:45 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def __setitem__(self, key, value): | 
					
						
							| 
									
										
										
										
											2001-09-28 19:01:26 +00:00
										 |  |  |         self.data[key] = ref(value, self.__makeremove(key)) | 
					
						
							| 
									
										
										
										
											2001-02-01 05:27:45 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def copy(self): | 
					
						
							| 
									
										
										
										
											2001-03-01 03:06:03 +00:00
										 |  |  |         new = WeakValueDictionary() | 
					
						
							| 
									
										
										
										
											2001-04-19 16:26:06 +00:00
										 |  |  |         for key, wr in self.data.items(): | 
					
						
							|  |  |  |             o = wr() | 
					
						
							| 
									
										
										
										
											2001-02-01 05:27:45 +00:00
										 |  |  |             if o is not None: | 
					
						
							|  |  |  |                 new[key] = o | 
					
						
							| 
									
										
										
										
											2001-03-01 03:06:03 +00:00
										 |  |  |         return new | 
					
						
							| 
									
										
										
										
											2001-02-01 05:27:45 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-16 17:34:48 +00:00
										 |  |  |     def get(self, key, default=None): | 
					
						
							| 
									
										
										
										
											2001-02-01 05:27:45 +00:00
										 |  |  |         try: | 
					
						
							| 
									
										
										
										
											2001-04-19 16:26:06 +00:00
										 |  |  |             wr = self.data[key] | 
					
						
							| 
									
										
										
										
											2001-02-01 05:27:45 +00:00
										 |  |  |         except KeyError: | 
					
						
							|  |  |  |             return default | 
					
						
							|  |  |  |         else: | 
					
						
							| 
									
										
										
										
											2001-04-19 16:26:06 +00:00
										 |  |  |             o = wr() | 
					
						
							| 
									
										
										
										
											2001-02-01 05:27:45 +00:00
										 |  |  |             if o is None: | 
					
						
							|  |  |  |                 # This should only happen | 
					
						
							|  |  |  |                 return default | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 return o | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def items(self): | 
					
						
							| 
									
										
										
										
											2001-02-02 15:13:24 +00:00
										 |  |  |         L = [] | 
					
						
							| 
									
										
										
										
											2001-04-19 16:26:06 +00:00
										 |  |  |         for key, wr in self.data.items(): | 
					
						
							|  |  |  |             o = wr() | 
					
						
							| 
									
										
										
										
											2001-02-01 05:27:45 +00:00
										 |  |  |             if o is not None: | 
					
						
							| 
									
										
										
										
											2001-02-02 15:13:24 +00:00
										 |  |  |                 L.append((key, o)) | 
					
						
							| 
									
										
										
										
											2001-02-01 05:27:45 +00:00
										 |  |  |         return L | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-05-02 05:43:09 +00:00
										 |  |  |     def iteritems(self): | 
					
						
							|  |  |  |         return WeakValuedItemIterator(self) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def iterkeys(self): | 
					
						
							|  |  |  |         return self.data.iterkeys() | 
					
						
							|  |  |  |     __iter__ = iterkeys | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def itervalues(self): | 
					
						
							|  |  |  |         return WeakValuedValueIterator(self) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-02-01 05:27:45 +00:00
										 |  |  |     def popitem(self): | 
					
						
							|  |  |  |         while 1: | 
					
						
							| 
									
										
										
										
											2001-04-19 16:26:06 +00:00
										 |  |  |             key, wr = self.data.popitem() | 
					
						
							|  |  |  |             o = wr() | 
					
						
							| 
									
										
										
										
											2001-02-01 05:27:45 +00:00
										 |  |  |             if o is not None: | 
					
						
							|  |  |  |                 return key, o | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def setdefault(self, key, default): | 
					
						
							|  |  |  |         try: | 
					
						
							| 
									
										
										
										
											2001-04-19 16:26:06 +00:00
										 |  |  |             wr = self.data[key] | 
					
						
							| 
									
										
										
										
											2001-02-01 05:27:45 +00:00
										 |  |  |         except KeyError: | 
					
						
							| 
									
										
										
										
											2001-09-28 19:01:26 +00:00
										 |  |  |             self.data[key] = ref(default, self.__makeremove(key)) | 
					
						
							| 
									
										
										
										
											2001-02-01 05:27:45 +00:00
										 |  |  |             return default | 
					
						
							|  |  |  |         else: | 
					
						
							| 
									
										
										
										
											2001-04-19 16:26:06 +00:00
										 |  |  |             return wr() | 
					
						
							| 
									
										
										
										
											2001-02-01 05:27:45 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def update(self, dict): | 
					
						
							|  |  |  |         d = self.data | 
					
						
							|  |  |  |         for key, o in dict.items(): | 
					
						
							| 
									
										
										
										
											2001-09-28 19:01:26 +00:00
										 |  |  |             d[key] = ref(o, self.__makeremove(key)) | 
					
						
							| 
									
										
										
										
											2001-02-01 05:27:45 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def values(self): | 
					
						
							|  |  |  |         L = [] | 
					
						
							| 
									
										
										
										
											2001-04-19 16:26:06 +00:00
										 |  |  |         for wr in self.data.values(): | 
					
						
							|  |  |  |             o = wr() | 
					
						
							| 
									
										
										
										
											2001-02-01 05:27:45 +00:00
										 |  |  |             if o is not None: | 
					
						
							|  |  |  |                 L.append(o) | 
					
						
							|  |  |  |         return L | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-28 19:01:26 +00:00
										 |  |  |     def __makeremove(self, key): | 
					
						
							|  |  |  |         def remove(o, selfref=ref(self), key=key): | 
					
						
							|  |  |  |             self = selfref() | 
					
						
							|  |  |  |             if self is not None: | 
					
						
							|  |  |  |                 del self.data[key] | 
					
						
							|  |  |  |         return remove | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-02-01 05:27:45 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-02-27 18:36:56 +00:00
										 |  |  | class WeakKeyDictionary(UserDict.UserDict): | 
					
						
							| 
									
										
										
										
											2001-04-19 16:26:06 +00:00
										 |  |  |     """ Mapping class that references keys weakly.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Entries in the dictionary will be discarded when there is no | 
					
						
							|  |  |  |     longer a strong reference to the key. This can be used to | 
					
						
							|  |  |  |     associate additional data with an object owned by other parts of | 
					
						
							|  |  |  |     an application without adding attributes to those objects. This | 
					
						
							|  |  |  |     can be especially useful with objects that override attribute | 
					
						
							|  |  |  |     accesses. | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2001-02-27 18:36:56 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def __init__(self, dict=None): | 
					
						
							|  |  |  |         self.data = {} | 
					
						
							| 
									
										
										
										
											2001-09-28 19:01:26 +00:00
										 |  |  |         def remove(k, selfref=ref(self)): | 
					
						
							|  |  |  |             self = selfref() | 
					
						
							|  |  |  |             if self is not None: | 
					
						
							|  |  |  |                 del self.data[k] | 
					
						
							| 
									
										
										
										
											2001-02-27 18:36:56 +00:00
										 |  |  |         self._remove = remove | 
					
						
							| 
									
										
										
										
											2002-06-10 20:00:52 +00:00
										 |  |  |         if dict is not None: self.update(dict) | 
					
						
							| 
									
										
										
										
											2001-02-27 18:36:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-06 14:51:01 +00:00
										 |  |  |     def __delitem__(self, key): | 
					
						
							|  |  |  |         for ref in self.data.iterkeys(): | 
					
						
							|  |  |  |             o = ref() | 
					
						
							|  |  |  |             if o == key: | 
					
						
							|  |  |  |                 del self.data[ref] | 
					
						
							|  |  |  |                 return | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-02-27 18:36:56 +00:00
										 |  |  |     def __getitem__(self, key): | 
					
						
							|  |  |  |         return self.data[ref(key)] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __repr__(self): | 
					
						
							|  |  |  |         return "<WeakKeyDictionary at %s>" % id(self) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __setitem__(self, key, value): | 
					
						
							|  |  |  |         self.data[ref(key, self._remove)] = value | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def copy(self): | 
					
						
							|  |  |  |         new = WeakKeyDictionary() | 
					
						
							|  |  |  |         for key, value in self.data.items(): | 
					
						
							|  |  |  |             o = key() | 
					
						
							|  |  |  |             if o is not None: | 
					
						
							|  |  |  |                 new[o] = value | 
					
						
							| 
									
										
										
										
											2001-03-01 03:06:03 +00:00
										 |  |  |         return new | 
					
						
							| 
									
										
										
										
											2001-02-27 18:36:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-16 17:34:48 +00:00
										 |  |  |     def get(self, key, default=None): | 
					
						
							| 
									
										
										
										
											2001-02-27 18:36:56 +00:00
										 |  |  |         return self.data.get(ref(key),default) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-16 17:34:48 +00:00
										 |  |  |     def has_key(self, key): | 
					
						
							| 
									
										
										
										
											2001-11-06 16:36:53 +00:00
										 |  |  |         try: | 
					
						
							|  |  |  |             wr = ref(key) | 
					
						
							|  |  |  |         except TypeError: | 
					
						
							|  |  |  |             return 0 | 
					
						
							| 
									
										
										
										
											2002-06-01 14:18:47 +00:00
										 |  |  |         return wr in self.data | 
					
						
							| 
									
										
										
										
											2001-04-16 17:34:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-06-01 14:18:47 +00:00
										 |  |  |     def __contains__(self, key): | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             wr = ref(key) | 
					
						
							|  |  |  |         except TypeError: | 
					
						
							|  |  |  |             return 0 | 
					
						
							|  |  |  |         return wr in self.data | 
					
						
							| 
									
										
										
										
											2002-07-16 21:35:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-02-27 18:36:56 +00:00
										 |  |  |     def items(self): | 
					
						
							|  |  |  |         L = [] | 
					
						
							|  |  |  |         for key, value in self.data.items(): | 
					
						
							|  |  |  |             o = key() | 
					
						
							|  |  |  |             if o is not None: | 
					
						
							|  |  |  |                 L.append((o, value)) | 
					
						
							|  |  |  |         return L | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-05-02 05:43:09 +00:00
										 |  |  |     def iteritems(self): | 
					
						
							|  |  |  |         return WeakKeyedItemIterator(self) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def iterkeys(self): | 
					
						
							|  |  |  |         return WeakKeyedKeyIterator(self) | 
					
						
							|  |  |  |     __iter__ = iterkeys | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def itervalues(self): | 
					
						
							|  |  |  |         return self.data.itervalues() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-16 17:34:48 +00:00
										 |  |  |     def keys(self): | 
					
						
							|  |  |  |         L = [] | 
					
						
							| 
									
										
										
										
											2001-04-19 16:26:06 +00:00
										 |  |  |         for wr in self.data.keys(): | 
					
						
							|  |  |  |             o = wr() | 
					
						
							| 
									
										
										
										
											2001-04-16 17:34:48 +00:00
										 |  |  |             if o is not None: | 
					
						
							|  |  |  |                 L.append(o) | 
					
						
							|  |  |  |         return L | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-02-27 18:36:56 +00:00
										 |  |  |     def popitem(self): | 
					
						
							|  |  |  |         while 1: | 
					
						
							|  |  |  |             key, value = self.data.popitem() | 
					
						
							|  |  |  |             o = key() | 
					
						
							|  |  |  |             if o is not None: | 
					
						
							|  |  |  |                 return o, value | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def setdefault(self, key, default): | 
					
						
							|  |  |  |         return self.data.setdefault(ref(key, self._remove),default) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def update(self, dict): | 
					
						
							|  |  |  |         d = self.data | 
					
						
							|  |  |  |         for key, value in dict.items(): | 
					
						
							| 
									
										
										
										
											2001-04-19 16:26:06 +00:00
										 |  |  |             d[ref(key, self._remove)] = value | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-02-27 18:36:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-05-02 05:43:09 +00:00
										 |  |  | class BaseIter: | 
					
						
							|  |  |  |     def __iter__(self): | 
					
						
							|  |  |  |         return self | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class WeakKeyedKeyIterator(BaseIter): | 
					
						
							|  |  |  |     def __init__(self, weakdict): | 
					
						
							|  |  |  |         self._next = weakdict.data.iterkeys().next | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def next(self): | 
					
						
							|  |  |  |         while 1: | 
					
						
							|  |  |  |             wr = self._next() | 
					
						
							|  |  |  |             obj = wr() | 
					
						
							|  |  |  |             if obj is not None: | 
					
						
							|  |  |  |                 return obj | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class WeakKeyedItemIterator(BaseIter): | 
					
						
							|  |  |  |     def __init__(self, weakdict): | 
					
						
							|  |  |  |         self._next = weakdict.data.iteritems().next | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def next(self): | 
					
						
							|  |  |  |         while 1: | 
					
						
							|  |  |  |             wr, value = self._next() | 
					
						
							|  |  |  |             key = wr() | 
					
						
							|  |  |  |             if key is not None: | 
					
						
							|  |  |  |                 return key, value | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class WeakValuedValueIterator(BaseIter): | 
					
						
							|  |  |  |     def __init__(self, weakdict): | 
					
						
							|  |  |  |         self._next = weakdict.data.itervalues().next | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def next(self): | 
					
						
							|  |  |  |         while 1: | 
					
						
							|  |  |  |             wr = self._next() | 
					
						
							|  |  |  |             obj = wr() | 
					
						
							|  |  |  |             if obj is not None: | 
					
						
							|  |  |  |                 return obj | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class WeakValuedItemIterator(BaseIter): | 
					
						
							|  |  |  |     def __init__(self, weakdict): | 
					
						
							|  |  |  |         self._next = weakdict.data.iteritems().next | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def next(self): | 
					
						
							|  |  |  |         while 1: | 
					
						
							|  |  |  |             key, wr = self._next() | 
					
						
							|  |  |  |             value = wr() | 
					
						
							|  |  |  |             if value is not None: | 
					
						
							|  |  |  |                 return key, value | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-02-01 05:27:45 +00:00
										 |  |  | # no longer needed | 
					
						
							|  |  |  | del UserDict |