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