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