Home | History | Annotate | Download | only in python2.7
      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())
    181