"""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, \
     ReferenceError, \
     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 __getitem__(self, key):
        o = self.data[key]()
        if o is None:
            raise KeyError, key
        else:
            return o

    def __repr__(self):
        return "<WeakValueDictionary at %s>" % id(self)

    def __setitem__(self, key, value):
        def remove(o, data=self.data, key=key):
            del data[key]
        self.data[key] = ref(value, remove)

    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):
        return WeakValuedItemIterator(self)

    def iterkeys(self):
        return self.data.iterkeys()
    __iter__ = iterkeys

    def itervalues(self):
        return WeakValuedValueIterator(self)

    def popitem(self):
        while 1:
            key, wr = self.data.popitem()
            o = wr()
            if o is not None:
                return key, o

    def setdefault(self, key, default):
        try:
            wr = self.data[key]
        except KeyError:
            def remove(o, data=self.data, key=key):
                del data[key]
            self.data[key] = ref(default, remove)
            return default
        else:
            return wr()

    def update(self, dict):
        d = self.data
        for key, o in dict.items():
            def remove(o, data=d, key=key):
                del data[key]
            d[key] = ref(o, remove)

    def values(self):
        L = []
        for wr in self.data.values():
            o = wr()
            if o is not None:
                L.append(o)
        return L


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 = {}
        if dict is not None: self.update(dict)
        def remove(k, data=self.data):
            del data[k]
        self._remove = remove

    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 has_key(self, key):
        return self.data.has_key(ref(key))

    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):
        return WeakKeyedItemIterator(self)

    def iterkeys(self):
        return WeakKeyedKeyIterator(self)
    __iter__ = iterkeys

    def itervalues(self):
        return self.data.itervalues()

    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 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():
            d[ref(key, self._remove)] = value


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


# no longer needed
del UserDict
