Home | History | Annotate | Download | only in Lib
      1 """A more or less complete user-defined wrapper around dictionary objects."""
      2 
      3 class 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 
    112 class IterableUserDict(UserDict):
    113     def __iter__(self):
    114         return iter(self.data)
    115 
    116 import _abcoll
    117 _abcoll.MutableMapping.register(IterableUserDict)
    118 
    119 
    120 class 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