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