| """Weak reference support for Python. | 
 |  | 
 | This module is an implementation of PEP 205: | 
 |  | 
 | http://python.sourceforge.net/peps/pep-0205.html | 
 | """ | 
 |  | 
 | # 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. | 
 |  | 
 | import UserDict | 
 |  | 
 | from _weakref import ( | 
 |      getweakrefcount, | 
 |      getweakrefs, | 
 |      ref, | 
 |      proxy, | 
 |      CallableProxyType, | 
 |      ProxyType, | 
 |      ReferenceType) | 
 |  | 
 |  | 
 | ProxyTypes = (ProxyType, CallableProxyType) | 
 |  | 
 | __all__ = ["ref", "proxy", "getweakrefcount", "getweakrefs", | 
 |            "WeakKeyDictionary", "ReferenceType", "ProxyType", | 
 |            "CallableProxyType", "ProxyTypes", "WeakValueDictionary"] | 
 |  | 
 |  | 
 | class WeakValueDictionary(UserDict.UserDict): | 
 |     """Mapping class that references values weakly. | 
 |  | 
 |     Entries in the dictionary will be discarded when no strong | 
 |     reference to the value exists anymore | 
 |     """ | 
 |     # We inherit the constructor without worrying about the input | 
 |     # dictionary; since it uses our .update() method, we get the right | 
 |     # checks (if the other dictionary is a WeakValueDictionary, | 
 |     # objects are unwrapped on the way out, and we always wrap on the | 
 |     # way in). | 
 |  | 
 |     def __init__(self, *args, **kw): | 
 |         def remove(wr, selfref=ref(self)): | 
 |             self = selfref() | 
 |             if self is not None: | 
 |                 del self.data[wr.key] | 
 |         self._remove = remove | 
 |         UserDict.UserDict.__init__(self, *args, **kw) | 
 |  | 
 |     def __getitem__(self, key): | 
 |         o = self.data[key]() | 
 |         if o is None: | 
 |             raise KeyError, key | 
 |         else: | 
 |             return o | 
 |  | 
 |     def __contains__(self, key): | 
 |         try: | 
 |             o = self.data[key]() | 
 |         except KeyError: | 
 |             return False | 
 |         return o is not None | 
 |  | 
 |     def __repr__(self): | 
 |         return "<WeakValueDictionary at %s>" % id(self) | 
 |  | 
 |     def __setitem__(self, key, value): | 
 |         self.data[key] = KeyedRef(value, self._remove, key) | 
 |  | 
 |     def copy(self): | 
 |         new = WeakValueDictionary() | 
 |         for key, wr in self.data.items(): | 
 |             o = wr() | 
 |             if o is not None: | 
 |                 new[key] = o | 
 |         return new | 
 |  | 
 |     def get(self, key, default=None): | 
 |         try: | 
 |             wr = self.data[key] | 
 |         except KeyError: | 
 |             return default | 
 |         else: | 
 |             o = wr() | 
 |             if o is None: | 
 |                 # This should only happen | 
 |                 return default | 
 |             else: | 
 |                 return o | 
 |  | 
 |     def items(self): | 
 |         L = [] | 
 |         for key, wr in self.data.items(): | 
 |             o = wr() | 
 |             if o is not None: | 
 |                 L.append((key, o)) | 
 |         return L | 
 |  | 
 |     def iteritems(self): | 
 |         for wr in self.data.values(): | 
 |             value = wr() | 
 |             if value is not None: | 
 |                 yield wr.key, value | 
 |  | 
 |     def iterkeys(self): | 
 |         return iter(self.data.keys()) | 
 |  | 
 |     def __iter__(self): | 
 |         return iter(self.data.keys()) | 
 |  | 
 |     def itervaluerefs(self): | 
 |         """Return an iterator that yields the weak references to the values. | 
 |  | 
 |         The references are not guaranteed to be 'live' at the time | 
 |         they are used, so the result of calling the references needs | 
 |         to be checked before being used.  This can be used to avoid | 
 |         creating references that will cause the garbage collector to | 
 |         keep the values around longer than needed. | 
 |  | 
 |         """ | 
 |         return self.data.values() | 
 |  | 
 |     def itervalues(self): | 
 |         for wr in self.data.values(): | 
 |             obj = wr() | 
 |             if obj is not None: | 
 |                 yield obj | 
 |  | 
 |     def popitem(self): | 
 |         while 1: | 
 |             key, wr = self.data.popitem() | 
 |             o = wr() | 
 |             if o is not None: | 
 |                 return key, o | 
 |  | 
 |     def pop(self, key, *args): | 
 |         try: | 
 |             o = self.data.pop(key)() | 
 |         except KeyError: | 
 |             if args: | 
 |                 return args[0] | 
 |             raise | 
 |         if o is None: | 
 |             raise KeyError, key | 
 |         else: | 
 |             return o | 
 |  | 
 |     def setdefault(self, key, default=None): | 
 |         try: | 
 |             wr = self.data[key] | 
 |         except KeyError: | 
 |             self.data[key] = KeyedRef(default, self._remove, key) | 
 |             return default | 
 |         else: | 
 |             return wr() | 
 |  | 
 |     def update(self, dict=None, **kwargs): | 
 |         d = self.data | 
 |         if dict is not None: | 
 |             if not hasattr(dict, "items"): | 
 |                 dict = type({})(dict) | 
 |             for key, o in dict.items(): | 
 |                 d[key] = KeyedRef(o, self._remove, key) | 
 |         if len(kwargs): | 
 |             self.update(kwargs) | 
 |  | 
 |     def valuerefs(self): | 
 |         """Return a list of weak references to the values. | 
 |  | 
 |         The references are not guaranteed to be 'live' at the time | 
 |         they are used, so the result of calling the references needs | 
 |         to be checked before being used.  This can be used to avoid | 
 |         creating references that will cause the garbage collector to | 
 |         keep the values around longer than needed. | 
 |  | 
 |         """ | 
 |         return self.data.values() | 
 |  | 
 |     def values(self): | 
 |         L = [] | 
 |         for wr in self.data.values(): | 
 |             o = wr() | 
 |             if o is not None: | 
 |                 L.append(o) | 
 |         return L | 
 |  | 
 |  | 
 | class KeyedRef(ref): | 
 |     """Specialized reference that includes a key corresponding to the value. | 
 |  | 
 |     This is used in the WeakValueDictionary to avoid having to create | 
 |     a function object for each key stored in the mapping.  A shared | 
 |     callback object can use the 'key' attribute of a KeyedRef instead | 
 |     of getting a reference to the key from an enclosing scope. | 
 |  | 
 |     """ | 
 |  | 
 |     __slots__ = "key", | 
 |  | 
 |     def __new__(type, ob, callback, key): | 
 |         self = ref.__new__(type, ob, callback) | 
 |         self.key = key | 
 |         return self | 
 |  | 
 |     def __init__(self, ob, callback, key): | 
 |         super().__init__(ob, callback) | 
 |  | 
 |  | 
 | class WeakKeyDictionary(UserDict.UserDict): | 
 |     """ 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. | 
 |     """ | 
 |  | 
 |     def __init__(self, dict=None): | 
 |         self.data = {} | 
 |         def remove(k, selfref=ref(self)): | 
 |             self = selfref() | 
 |             if self is not None: | 
 |                 del self.data[k] | 
 |         self._remove = remove | 
 |         if dict is not None: self.update(dict) | 
 |  | 
 |     def __delitem__(self, key): | 
 |         del self.data[ref(key)] | 
 |  | 
 |     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 | 
 |         return new | 
 |  | 
 |     def get(self, key, default=None): | 
 |         return self.data.get(ref(key),default) | 
 |  | 
 |     def __contains__(self, key): | 
 |         try: | 
 |             wr = ref(key) | 
 |         except TypeError: | 
 |             return 0 | 
 |         return wr in self.data | 
 |  | 
 |     def items(self): | 
 |         L = [] | 
 |         for key, value in self.data.items(): | 
 |             o = key() | 
 |             if o is not None: | 
 |                 L.append((o, value)) | 
 |         return L | 
 |  | 
 |     def iteritems(self): | 
 |         for wr, value in self.data.items(): | 
 |             key = wr() | 
 |             if key is not None: | 
 |                 yield key, value | 
 |  | 
 |     def iterkeyrefs(self): | 
 |         """Return an iterator that yields the weak references to the keys. | 
 |  | 
 |         The references are not guaranteed to be 'live' at the time | 
 |         they are used, so the result of calling the references needs | 
 |         to be checked before being used.  This can be used to avoid | 
 |         creating references that will cause the garbage collector to | 
 |         keep the keys around longer than needed. | 
 |  | 
 |         """ | 
 |         return self.data.keys() | 
 |  | 
 |     def iterkeys(self): | 
 |         for wr in self.data.keys(): | 
 |             obj = wr() | 
 |             if obj is not None: | 
 |                 yield obj | 
 |  | 
 |     def __iter__(self): | 
 |         return iter(self.keys()) | 
 |  | 
 |     def itervalues(self): | 
 |         return iter(self.data.values()) | 
 |  | 
 |     def keyrefs(self): | 
 |         """Return a list of weak references to the keys. | 
 |  | 
 |         The references are not guaranteed to be 'live' at the time | 
 |         they are used, so the result of calling the references needs | 
 |         to be checked before being used.  This can be used to avoid | 
 |         creating references that will cause the garbage collector to | 
 |         keep the keys around longer than needed. | 
 |  | 
 |         """ | 
 |         return self.data.keys() | 
 |  | 
 |     def keys(self): | 
 |         L = [] | 
 |         for wr in self.data.keys(): | 
 |             o = wr() | 
 |             if o is not None: | 
 |                 L.append(o) | 
 |         return L | 
 |  | 
 |     def popitem(self): | 
 |         while 1: | 
 |             key, value = self.data.popitem() | 
 |             o = key() | 
 |             if o is not None: | 
 |                 return o, value | 
 |  | 
 |     def pop(self, key, *args): | 
 |         return self.data.pop(ref(key), *args) | 
 |  | 
 |     def setdefault(self, key, default=None): | 
 |         return self.data.setdefault(ref(key, self._remove),default) | 
 |  | 
 |     def update(self, dict=None, **kwargs): | 
 |         d = self.data | 
 |         if dict is not None: | 
 |             if not hasattr(dict, "items"): | 
 |                 dict = type({})(dict) | 
 |             for key, value in dict.items(): | 
 |                 d[ref(key, self._remove)] = value | 
 |         if len(kwargs): | 
 |             self.update(kwargs) |