1edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep"""A more or less complete user-defined wrapper around dictionary objects.""" 2edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 3edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepclass UserDict: 4edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def __init__(self, dict=None, **kwargs): 5edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self.data = {} 6edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if dict is not None: 7edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self.update(dict) 8edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if len(kwargs): 9edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self.update(kwargs) 10edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def __repr__(self): return repr(self.data) 11edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def __cmp__(self, dict): 12edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if isinstance(dict, UserDict): 13edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return cmp(self.data, dict.data) 14edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep else: 15edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return cmp(self.data, dict) 16edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep __hash__ = None # Avoid Py3k warning 17edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def __len__(self): return len(self.data) 18edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def __getitem__(self, key): 19edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if key in self.data: 20edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return self.data[key] 21edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if hasattr(self.__class__, "__missing__"): 22edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return self.__class__.__missing__(self, key) 23edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep raise KeyError(key) 24edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def __setitem__(self, key, item): self.data[key] = item 25edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def __delitem__(self, key): del self.data[key] 26edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def clear(self): self.data.clear() 27edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def copy(self): 28edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if self.__class__ is UserDict: 29edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return UserDict(self.data.copy()) 30edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep import copy 31edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep data = self.data 32edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep try: 33edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self.data = {} 34edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep c = copy.copy(self) 35edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep finally: 36edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self.data = data 37edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep c.update(self) 38edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return c 39edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def keys(self): return self.data.keys() 40edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def items(self): return self.data.items() 41edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def iteritems(self): return self.data.iteritems() 42edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def iterkeys(self): return self.data.iterkeys() 43edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def itervalues(self): return self.data.itervalues() 44edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def values(self): return self.data.values() 45edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def has_key(self, key): return key in self.data 46edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def update(self, dict=None, **kwargs): 47edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if dict is None: 48edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep pass 49edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep elif isinstance(dict, UserDict): 50edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self.data.update(dict.data) 51edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep elif isinstance(dict, type({})) or not hasattr(dict, 'items'): 52edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self.data.update(dict) 53edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep else: 54edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep for k, v in dict.items(): 55edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self[k] = v 56edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if len(kwargs): 57edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self.data.update(kwargs) 58edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def get(self, key, failobj=None): 59edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if key not in self: 60edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return failobj 61edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return self[key] 62edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def setdefault(self, key, failobj=None): 63edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if key not in self: 64edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self[key] = failobj 65edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return self[key] 66edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def pop(self, key, *args): 67edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return self.data.pop(key, *args) 68edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def popitem(self): 69edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return self.data.popitem() 70edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def __contains__(self, key): 71edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return key in self.data 72edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep @classmethod 73edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def fromkeys(cls, iterable, value=None): 74edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep d = cls() 75edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep for key in iterable: 76edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep d[key] = value 77edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return d 78edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 79edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepclass IterableUserDict(UserDict): 80edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def __iter__(self): 81edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return iter(self.data) 82edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 83edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepimport _abcoll 84edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep_abcoll.MutableMapping.register(IterableUserDict) 85edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 86edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 87edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepclass DictMixin: 88edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep # Mixin defining all dictionary methods for classes that already have 89edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep # a minimum dictionary interface including getitem, setitem, delitem, 90edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep # and keys. Without knowledge of the subclass constructor, the mixin 91edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep # does not define __init__() or copy(). In addition to the four base 92edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep # methods, progressively more efficiency comes with defining 93edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep # __contains__(), __iter__(), and iteritems(). 94edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 95edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep # second level definitions support higher levels 96edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def __iter__(self): 97edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep for k in self.keys(): 98edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep yield k 99edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def has_key(self, key): 100edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep try: 101edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self[key] 102edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep except KeyError: 103edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return False 104edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return True 105edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def __contains__(self, key): 106edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return self.has_key(key) 107edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 108edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep # third level takes advantage of second level definitions 109edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def iteritems(self): 110edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep for k in self: 111edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep yield (k, self[k]) 112edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def iterkeys(self): 113edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return self.__iter__() 114edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep 115edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep # fourth level uses definitions from lower levels 116edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def itervalues(self): 117edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep for _, v in self.iteritems(): 118edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep yield v 119edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def values(self): 120edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return [v for _, v in self.iteritems()] 121edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def items(self): 122edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return list(self.iteritems()) 123edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def clear(self): 124edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep for key in self.keys(): 125edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep del self[key] 126edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def setdefault(self, key, default=None): 127edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep try: 128edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return self[key] 129edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep except KeyError: 130edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self[key] = default 131edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return default 132edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def pop(self, key, *args): 133edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if len(args) > 1: 134edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep raise TypeError, "pop expected at most 2 arguments, got "\ 135edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep + repr(1 + len(args)) 136edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep try: 137edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep value = self[key] 138edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep except KeyError: 139edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if args: 140edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return args[0] 141edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep raise 142edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep del self[key] 143edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return value 144edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def popitem(self): 145edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep try: 146edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep k, v = self.iteritems().next() 147edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep except StopIteration: 148edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep raise KeyError, 'container is empty' 149edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep del self[k] 150edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return (k, v) 151edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def update(self, other=None, **kwargs): 152edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep # Make progressively weaker assumptions about "other" 153edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if other is None: 154edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep pass 155edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep elif hasattr(other, 'iteritems'): # iteritems saves memory and lookups 156edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep for k, v in other.iteritems(): 157edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self[k] = v 158edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep elif hasattr(other, 'keys'): 159edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep for k in other.keys(): 160edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self[k] = other[k] 161edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep else: 162edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep for k, v in other: 163edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self[k] = v 164edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if kwargs: 165edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep self.update(kwargs) 166edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def get(self, key, default=None): 167edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep try: 168edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return self[key] 169edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep except KeyError: 170edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return default 171edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def __repr__(self): 172edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return repr(dict(self.iteritems())) 173edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def __cmp__(self, other): 174edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if other is None: 175edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return 1 176edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep if isinstance(other, DictMixin): 177edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep other = dict(other.iteritems()) 178edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return cmp(dict(self.iteritems()), other) 179edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep def __len__(self): 180edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep return len(self.keys()) 181