0001"""
0002A backport of UserDict.DictMixin for pre-python-2.4
0003"""
0004__all__ = ['DictMixin']
0005
0006try:
0007    from UserDict import DictMixin
0008except ImportError:
0009    class DictMixin:
0010        # Mixin defining all dictionary methods for classes that already have
0011        # a minimum dictionary interface including getitem, setitem, delitem,
0012        # and keys. Without knowledge of the subclass constructor, the mixin
0013        # does not define __init__() or copy().  In addition to the four base
0014        # methods, progressively more efficiency comes with defining
0015        # __contains__(), __iter__(), and iteritems().
0016
0017        # second level definitions support higher levels
0018        def __iter__(self):
0019            for k in self.keys():
0020                yield k
0021        def has_key(self, key):
0022            try:
0023                value = self[key]
0024            except KeyError:
0025                return False
0026            return True
0027        def __contains__(self, key):
0028            return self.has_key(key)
0029
0030        # third level takes advantage of second level definitions
0031        def iteritems(self):
0032            for k in self:
0033                yield (k, self[k])
0034        def iterkeys(self):
0035            return self.__iter__()
0036
0037        # fourth level uses definitions from lower levels
0038        def itervalues(self):
0039            for _, v in self.iteritems():
0040                yield v
0041        def values(self):
0042            return [v for _, v in self.iteritems()]
0043        def items(self):
0044            return list(self.iteritems())
0045        def clear(self):
0046            for key in self.keys():
0047                del self[key]
0048        def setdefault(self, key, default=None):
0049            try:
0050                return self[key]
0051            except KeyError:
0052                self[key] = default
0053            return default
0054        def pop(self, key, *args):
0055            if len(args) > 1:
0056                raise TypeError, "pop expected at most 2 arguments, got "                                    + repr(1 + len(args))
0058            try:
0059                value = self[key]
0060            except KeyError:
0061                if args:
0062                    return args[0]
0063                raise
0064            del self[key]
0065            return value
0066        def popitem(self):
0067            try:
0068                k, v = self.iteritems().next()
0069            except StopIteration:
0070                raise KeyError, 'container is empty'
0071            del self[k]
0072            return (k, v)
0073        def update(self, other=None, **kwargs):
0074            # Make progressively weaker assumptions about "other"
0075            if other is None:
0076                pass
0077            elif hasattr(other, 'iteritems'):  # iteritems saves memory and lookups
0078                for k, v in other.iteritems():
0079                    self[k] = v
0080            elif hasattr(other, 'keys'):
0081                for k in other.keys():
0082                    self[k] = other[k]
0083            else:
0084                for k, v in other:
0085                    self[k] = v
0086            if kwargs:
0087                self.update(kwargs)
0088        def get(self, key, default=None):
0089            try:
0090                return self[key]
0091            except KeyError:
0092                return default
0093        def __repr__(self):
0094            return repr(dict(self.iteritems()))
0095        def __cmp__(self, other):
0096            if other is None:
0097                return 1
0098            if isinstance(other, DictMixin):
0099                other = dict(other.iteritems())
0100            return cmp(dict(self.iteritems()), other)
0101        def __len__(self):
0102            return len(self.keys())