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