10a8c90248264a8b26970b4473770bcc3df8515fJosh Gao"""A more or less complete user-defined wrapper around dictionary objects.""" 20a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 30a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoclass UserDict: 40a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def __init__(self, dict=None, **kwargs): 50a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.data = {} 60a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if dict is not None: 70a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.update(dict) 80a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if len(kwargs): 90a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.update(kwargs) 100a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def __repr__(self): return repr(self.data) 110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def __cmp__(self, dict): 120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if isinstance(dict, UserDict): 130a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return cmp(self.data, dict.data) 140a8c90248264a8b26970b4473770bcc3df8515fJosh Gao else: 150a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return cmp(self.data, dict) 160a8c90248264a8b26970b4473770bcc3df8515fJosh Gao __hash__ = None # Avoid Py3k warning 170a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def __len__(self): return len(self.data) 180a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def __getitem__(self, key): 190a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if key in self.data: 200a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return self.data[key] 210a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if hasattr(self.__class__, "__missing__"): 220a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return self.__class__.__missing__(self, key) 230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao raise KeyError(key) 240a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def __setitem__(self, key, item): self.data[key] = item 250a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def __delitem__(self, key): del self.data[key] 260a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def clear(self): self.data.clear() 270a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def copy(self): 280a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if self.__class__ is UserDict: 290a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return UserDict(self.data.copy()) 300a8c90248264a8b26970b4473770bcc3df8515fJosh Gao import copy 310a8c90248264a8b26970b4473770bcc3df8515fJosh Gao data = self.data 320a8c90248264a8b26970b4473770bcc3df8515fJosh Gao try: 330a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.data = {} 340a8c90248264a8b26970b4473770bcc3df8515fJosh Gao c = copy.copy(self) 350a8c90248264a8b26970b4473770bcc3df8515fJosh Gao finally: 360a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.data = data 370a8c90248264a8b26970b4473770bcc3df8515fJosh Gao c.update(self) 380a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return c 390a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def keys(self): return self.data.keys() 400a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def items(self): return self.data.items() 410a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def iteritems(self): return self.data.iteritems() 420a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def iterkeys(self): return self.data.iterkeys() 430a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def itervalues(self): return self.data.itervalues() 440a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def values(self): return self.data.values() 450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def has_key(self, key): return key in self.data 460a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def update(self, dict=None, **kwargs): 470a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if dict is None: 480a8c90248264a8b26970b4473770bcc3df8515fJosh Gao pass 490a8c90248264a8b26970b4473770bcc3df8515fJosh Gao elif isinstance(dict, UserDict): 500a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.data.update(dict.data) 510a8c90248264a8b26970b4473770bcc3df8515fJosh Gao elif isinstance(dict, type({})) or not hasattr(dict, 'items'): 520a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.data.update(dict) 530a8c90248264a8b26970b4473770bcc3df8515fJosh Gao else: 540a8c90248264a8b26970b4473770bcc3df8515fJosh Gao for k, v in dict.items(): 550a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self[k] = v 560a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if len(kwargs): 570a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.data.update(kwargs) 580a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def get(self, key, failobj=None): 590a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if key not in self: 600a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return failobj 610a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return self[key] 620a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def setdefault(self, key, failobj=None): 630a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if key not in self: 640a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self[key] = failobj 650a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return self[key] 660a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def pop(self, key, *args): 670a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return self.data.pop(key, *args) 680a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def popitem(self): 690a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return self.data.popitem() 700a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def __contains__(self, key): 710a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return key in self.data 720a8c90248264a8b26970b4473770bcc3df8515fJosh Gao @classmethod 730a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def fromkeys(cls, iterable, value=None): 740a8c90248264a8b26970b4473770bcc3df8515fJosh Gao d = cls() 750a8c90248264a8b26970b4473770bcc3df8515fJosh Gao for key in iterable: 760a8c90248264a8b26970b4473770bcc3df8515fJosh Gao d[key] = value 770a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return d 780a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 790a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoclass IterableUserDict(UserDict): 800a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def __iter__(self): 810a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return iter(self.data) 820a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 830a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoimport _abcoll 840a8c90248264a8b26970b4473770bcc3df8515fJosh Gao_abcoll.MutableMapping.register(IterableUserDict) 850a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 860a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 870a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoclass DictMixin: 880a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # Mixin defining all dictionary methods for classes that already have 890a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # a minimum dictionary interface including getitem, setitem, delitem, 900a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # and keys. Without knowledge of the subclass constructor, the mixin 910a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # does not define __init__() or copy(). In addition to the four base 920a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # methods, progressively more efficiency comes with defining 930a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # __contains__(), __iter__(), and iteritems(). 940a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 950a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # second level definitions support higher levels 960a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def __iter__(self): 970a8c90248264a8b26970b4473770bcc3df8515fJosh Gao for k in self.keys(): 980a8c90248264a8b26970b4473770bcc3df8515fJosh Gao yield k 990a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def has_key(self, key): 1000a8c90248264a8b26970b4473770bcc3df8515fJosh Gao try: 1010a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self[key] 1020a8c90248264a8b26970b4473770bcc3df8515fJosh Gao except KeyError: 1030a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return False 1040a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return True 1050a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def __contains__(self, key): 1060a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return self.has_key(key) 1070a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1080a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # third level takes advantage of second level definitions 1090a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def iteritems(self): 1100a8c90248264a8b26970b4473770bcc3df8515fJosh Gao for k in self: 1110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao yield (k, self[k]) 1120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def iterkeys(self): 1130a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return self.__iter__() 1140a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1150a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # fourth level uses definitions from lower levels 1160a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def itervalues(self): 1170a8c90248264a8b26970b4473770bcc3df8515fJosh Gao for _, v in self.iteritems(): 1180a8c90248264a8b26970b4473770bcc3df8515fJosh Gao yield v 1190a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def values(self): 1200a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return [v for _, v in self.iteritems()] 1210a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def items(self): 1220a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return list(self.iteritems()) 1230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def clear(self): 1240a8c90248264a8b26970b4473770bcc3df8515fJosh Gao for key in self.keys(): 1250a8c90248264a8b26970b4473770bcc3df8515fJosh Gao del self[key] 1260a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def setdefault(self, key, default=None): 1270a8c90248264a8b26970b4473770bcc3df8515fJosh Gao try: 1280a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return self[key] 1290a8c90248264a8b26970b4473770bcc3df8515fJosh Gao except KeyError: 1300a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self[key] = default 1310a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return default 1320a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def pop(self, key, *args): 1330a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if len(args) > 1: 1340a8c90248264a8b26970b4473770bcc3df8515fJosh Gao raise TypeError, "pop expected at most 2 arguments, got "\ 1350a8c90248264a8b26970b4473770bcc3df8515fJosh Gao + repr(1 + len(args)) 1360a8c90248264a8b26970b4473770bcc3df8515fJosh Gao try: 1370a8c90248264a8b26970b4473770bcc3df8515fJosh Gao value = self[key] 1380a8c90248264a8b26970b4473770bcc3df8515fJosh Gao except KeyError: 1390a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if args: 1400a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return args[0] 1410a8c90248264a8b26970b4473770bcc3df8515fJosh Gao raise 1420a8c90248264a8b26970b4473770bcc3df8515fJosh Gao del self[key] 1430a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return value 1440a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def popitem(self): 1450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao try: 1460a8c90248264a8b26970b4473770bcc3df8515fJosh Gao k, v = self.iteritems().next() 1470a8c90248264a8b26970b4473770bcc3df8515fJosh Gao except StopIteration: 1480a8c90248264a8b26970b4473770bcc3df8515fJosh Gao raise KeyError, 'container is empty' 1490a8c90248264a8b26970b4473770bcc3df8515fJosh Gao del self[k] 1500a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return (k, v) 1510a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def update(self, other=None, **kwargs): 1520a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # Make progressively weaker assumptions about "other" 1530a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if other is None: 1540a8c90248264a8b26970b4473770bcc3df8515fJosh Gao pass 1550a8c90248264a8b26970b4473770bcc3df8515fJosh Gao elif hasattr(other, 'iteritems'): # iteritems saves memory and lookups 1560a8c90248264a8b26970b4473770bcc3df8515fJosh Gao for k, v in other.iteritems(): 1570a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self[k] = v 1580a8c90248264a8b26970b4473770bcc3df8515fJosh Gao elif hasattr(other, 'keys'): 1590a8c90248264a8b26970b4473770bcc3df8515fJosh Gao for k in other.keys(): 1600a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self[k] = other[k] 1610a8c90248264a8b26970b4473770bcc3df8515fJosh Gao else: 1620a8c90248264a8b26970b4473770bcc3df8515fJosh Gao for k, v in other: 1630a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self[k] = v 1640a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if kwargs: 1650a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.update(kwargs) 1660a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def get(self, key, default=None): 1670a8c90248264a8b26970b4473770bcc3df8515fJosh Gao try: 1680a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return self[key] 1690a8c90248264a8b26970b4473770bcc3df8515fJosh Gao except KeyError: 1700a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return default 1710a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def __repr__(self): 1720a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return repr(dict(self.iteritems())) 1730a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def __cmp__(self, other): 1740a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if other is None: 1750a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return 1 1760a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if isinstance(other, DictMixin): 1770a8c90248264a8b26970b4473770bcc3df8515fJosh Gao other = dict(other.iteritems()) 1780a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return cmp(dict(self.iteritems()), other) 1790a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def __len__(self): 1800a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return len(self.keys()) 181