#
#  weak proxy maps
#  Module and documentation by Eric S. Tiedemann <est@hyperreal.org>
#

import _dict

class proxymap:
    "A weak proxy map class."

    def __init__(self, map):
        self.__map = map
        self.__weaks = _dict.dict()

    # Note how we check self.__weaks.get() returns from the dict
    # explicitly against None throughout.  Other objects can be false,
    # after all.

    def __reload(self, k):
        v = self.__map[k]
        self.__weaks[k] = v
        return v

    def __setitem__(self, k, v):
        self.__map[k] = v

        # No need for a new weak entry if a client is just writing through
        # a modified version of the unique object for this key.
        v1 = self.__weaks.get(k)

        # Explicitly check for None, since other objects could be false.
        if v != None and v1 != v:
            self.__weaks[k] = v
            
    def __len__(self): return len(self.__map)
    
    def __getitem__(self, k):
        v = self.__weaks.get(k)
        if v != None:
            return v
        else:
            return self.__reload(k)

    
    def get(self, k, default = None):
        v = self.__weaks.get(k)
        if v != None:
            return v
        elif self.__map.has_key(k):
            return self.__reload(k)
        else:
            return default

    def has_key(self, k):
        return self.__weaks.has_key(k) or self.__map.has_key(k)

    def keys(self):
        return self.__map.keys()
    
    def __delitem__(self, k):
        del self.__map[k]
        if self.__weaks.has_key(k):
            del self.__weaks[k]

    def clear(self):
        self.__map.clear()
        self.__weaks.clear()

    def copy(self):
        m = self.__map.copy()
        return proxymap(m)

    def update(self, b):
        for k, v in b.items(): self[k] = v

    # People generally shouldn't be using these last two on weak proxy
    # maps, but they may be convenient occasionally, especially during
    # development.  They will both, of course, create proxy map
    # entries for every entry in the source map.

    def items(self):
        __builtin__.map(lambda k, self=self: (k, self[k]), self.__map.keys())
        
    def values(self):
        __builtin__.map(lambda k, self=self: self[k], self.__map.keys())
