1*e1fe3e4aSElliott Hughes"""Misc dict tools.""" 2*e1fe3e4aSElliott Hughes 3*e1fe3e4aSElliott Hughes__all__ = ["hashdict"] 4*e1fe3e4aSElliott Hughes 5*e1fe3e4aSElliott Hughes 6*e1fe3e4aSElliott Hughes# https://stackoverflow.com/questions/1151658/python-hashable-dicts 7*e1fe3e4aSElliott Hughesclass hashdict(dict): 8*e1fe3e4aSElliott Hughes """ 9*e1fe3e4aSElliott Hughes hashable dict implementation, suitable for use as a key into 10*e1fe3e4aSElliott Hughes other dicts. 11*e1fe3e4aSElliott Hughes 12*e1fe3e4aSElliott Hughes >>> h1 = hashdict({"apples": 1, "bananas":2}) 13*e1fe3e4aSElliott Hughes >>> h2 = hashdict({"bananas": 3, "mangoes": 5}) 14*e1fe3e4aSElliott Hughes >>> h1+h2 15*e1fe3e4aSElliott Hughes hashdict(apples=1, bananas=3, mangoes=5) 16*e1fe3e4aSElliott Hughes >>> d1 = {} 17*e1fe3e4aSElliott Hughes >>> d1[h1] = "salad" 18*e1fe3e4aSElliott Hughes >>> d1[h1] 19*e1fe3e4aSElliott Hughes 'salad' 20*e1fe3e4aSElliott Hughes >>> d1[h2] 21*e1fe3e4aSElliott Hughes Traceback (most recent call last): 22*e1fe3e4aSElliott Hughes ... 23*e1fe3e4aSElliott Hughes KeyError: hashdict(bananas=3, mangoes=5) 24*e1fe3e4aSElliott Hughes 25*e1fe3e4aSElliott Hughes based on answers from 26*e1fe3e4aSElliott Hughes http://stackoverflow.com/questions/1151658/python-hashable-dicts 27*e1fe3e4aSElliott Hughes 28*e1fe3e4aSElliott Hughes """ 29*e1fe3e4aSElliott Hughes 30*e1fe3e4aSElliott Hughes def __key(self): 31*e1fe3e4aSElliott Hughes return tuple(sorted(self.items())) 32*e1fe3e4aSElliott Hughes 33*e1fe3e4aSElliott Hughes def __repr__(self): 34*e1fe3e4aSElliott Hughes return "{0}({1})".format( 35*e1fe3e4aSElliott Hughes self.__class__.__name__, 36*e1fe3e4aSElliott Hughes ", ".join("{0}={1}".format(str(i[0]), repr(i[1])) for i in self.__key()), 37*e1fe3e4aSElliott Hughes ) 38*e1fe3e4aSElliott Hughes 39*e1fe3e4aSElliott Hughes def __hash__(self): 40*e1fe3e4aSElliott Hughes return hash(self.__key()) 41*e1fe3e4aSElliott Hughes 42*e1fe3e4aSElliott Hughes def __setitem__(self, key, value): 43*e1fe3e4aSElliott Hughes raise TypeError( 44*e1fe3e4aSElliott Hughes "{0} does not support item assignment".format(self.__class__.__name__) 45*e1fe3e4aSElliott Hughes ) 46*e1fe3e4aSElliott Hughes 47*e1fe3e4aSElliott Hughes def __delitem__(self, key): 48*e1fe3e4aSElliott Hughes raise TypeError( 49*e1fe3e4aSElliott Hughes "{0} does not support item assignment".format(self.__class__.__name__) 50*e1fe3e4aSElliott Hughes ) 51*e1fe3e4aSElliott Hughes 52*e1fe3e4aSElliott Hughes def clear(self): 53*e1fe3e4aSElliott Hughes raise TypeError( 54*e1fe3e4aSElliott Hughes "{0} does not support item assignment".format(self.__class__.__name__) 55*e1fe3e4aSElliott Hughes ) 56*e1fe3e4aSElliott Hughes 57*e1fe3e4aSElliott Hughes def pop(self, *args, **kwargs): 58*e1fe3e4aSElliott Hughes raise TypeError( 59*e1fe3e4aSElliott Hughes "{0} does not support item assignment".format(self.__class__.__name__) 60*e1fe3e4aSElliott Hughes ) 61*e1fe3e4aSElliott Hughes 62*e1fe3e4aSElliott Hughes def popitem(self, *args, **kwargs): 63*e1fe3e4aSElliott Hughes raise TypeError( 64*e1fe3e4aSElliott Hughes "{0} does not support item assignment".format(self.__class__.__name__) 65*e1fe3e4aSElliott Hughes ) 66*e1fe3e4aSElliott Hughes 67*e1fe3e4aSElliott Hughes def setdefault(self, *args, **kwargs): 68*e1fe3e4aSElliott Hughes raise TypeError( 69*e1fe3e4aSElliott Hughes "{0} does not support item assignment".format(self.__class__.__name__) 70*e1fe3e4aSElliott Hughes ) 71*e1fe3e4aSElliott Hughes 72*e1fe3e4aSElliott Hughes def update(self, *args, **kwargs): 73*e1fe3e4aSElliott Hughes raise TypeError( 74*e1fe3e4aSElliott Hughes "{0} does not support item assignment".format(self.__class__.__name__) 75*e1fe3e4aSElliott Hughes ) 76*e1fe3e4aSElliott Hughes 77*e1fe3e4aSElliott Hughes # update is not ok because it mutates the object 78*e1fe3e4aSElliott Hughes # __add__ is ok because it creates a new object 79*e1fe3e4aSElliott Hughes # while the new object is under construction, it's ok to mutate it 80*e1fe3e4aSElliott Hughes def __add__(self, right): 81*e1fe3e4aSElliott Hughes result = hashdict(self) 82*e1fe3e4aSElliott Hughes dict.update(result, right) 83*e1fe3e4aSElliott Hughes return result 84