#!/usr/bin/env python
# Copyright (c) 2002 Nathan Sharfi
# Copyright terms are included in a file called 'license.txt'.

class MultiDict:
    """I am a structure that holds (key, value) pairs where more than one pair
    may have the same key."""
    def __init__(self, other=None):
        self.__rep = {}
        if other:
            self.__rep.update(other) # .update, or something else?

    def __len__(self):
        return len(self.__rep)

    def __repr__(self):
        return repr(self.__rep)

    def __str__(self):
        return repr(self)

    def __cmp__(self, other):
        return cmp(self.__rep, other.__rep)

    def clear(self):
        "Empties the multidict."
        self.__rep.clear()

    def __contains__(self, k):
        "Returns True if k is in the multidict."
        return k in self.__rep

    def insert(self, tup):
        "Inserts a 2-tuple into the multidict."
        if tup[0] in self.__rep:
            self.__rep[tup[0]].append(tup[1])
        else:
            self.__rep[tup[0]] = [tup[1]]

    def remove(self, k, v=None):
        """Removes pairs out of the multidict.
        If v is not given, then all pairs with k as the key will be removed."""
        if not v:
            del self.__rep[k]
        else:
            self.__rep[k].remove(v)

    
    def get(self, k):
        "Returns a list of elements that have k as their key."
        return self.__rep[k]

    def __iter__(self):
        return self.iteritems()

    ###########################################################################
    def iterkeys(self):
        """Returns an iterator over the keys in the mapping."""
        return iter(self.keys())
    
    def itervalues(self):
        """Returns an iterator over the values in the mapping."""
        return iter(self.values())

    def iteritems(self):
        """Returns an iterator over (key, value) pairs in the mapping."""
        return iter(self.items())

    ###########################################################################
    def keys(self):
        """Returns a list of the keys in the mapping."""
        return self.__rep.keys()

    def values(self):
        """Returns a list of value lists in the mapping."""
        return self.__rep.values()

    def items(self):
        """Returns a list of (key, value) pairs in the mapping."""
        l = []
        for k, vs in self.__rep.iteritems():
            for v in vs:
                l.append(tuple([k, v]))
        return l        

##     ### Could we support other traversal orders? ###

class InsensitiveDict(dict):
    def __init__(self, other=None):
        dict.__init__(self)
        if other:
            self.update(other)
        
    def __getitem__(self, k):
        if isinstance(k, str):
            return dict.__getitem__(self, k.lower())
        else:
            return dict.__getitem__(self, k)

    def __setitem__(self, k, v):
        if isinstance(k, str):
            dict.__setitem__(self, k.lower(), v) #[k.lower()] = v
        else:
            dict.__setitem__(self, k, v)

    def update(self, other):
        for k in other.keys():
            self[k] = other[k]

class InsensitiveMultiDict(MultiDict):
    def __init__(self, other): # make sure that the MD uses an ID
        MultiDict.__init__(self, InsensitiveDict(other))
        
if __name__ == '__main__':
    md = MultiDict({'k': ['v', 'w'], 'l': ['x', 'y']})
    
    for k, v in md:
        print
        print "THE KEY:   ", k
        print "THE VALUE: ", v
