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