Lichen

lib/UserDict.py

203:e28858d7f9d5
2016-11-21 Paul Boddie Added alias serialisation in order to preserve origin information for imported instances in the cached data.
     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 class DictMixin:    84     # Mixin defining all dictionary methods for classes that already have    85     # a minimum dictionary interface including getitem, setitem, delitem,    86     # and keys. Without knowledge of the subclass constructor, the mixin    87     # does not define __init__() or copy().  In addition to the four base    88     # methods, progressively more efficiency comes with defining    89     # __contains__(), __iter__(), and iteritems().    90     91     # second level definitions support higher levels    92     def __iter__(self):    93         for k in self.keys():    94             yield k    95     def has_key(self, key):    96         try:    97             self[key]    98         except KeyError:    99             return False   100         return True   101     def __contains__(self, key):   102         return self.has_key(key)   103    104     # third level takes advantage of second level definitions   105     def iteritems(self):   106         for k in self:   107             yield (k, self[k])   108     def iterkeys(self):   109         return self.__iter__()   110    111     # fourth level uses definitions from lower levels   112     def itervalues(self):   113         for _, v in self.iteritems():   114             yield v   115     def values(self):   116         return [v for _, v in self.iteritems()]   117     def items(self):   118         return list(self.iteritems())   119     def clear(self):   120         for key in self.keys():   121             del self[key]   122     def setdefault(self, key, default=None):   123         try:   124             return self[key]   125         except KeyError:   126             self[key] = default   127         return default   128     def pop(self, key, *args):   129         if len(args) > 1:   130             raise TypeError, "pop expected at most 2 arguments, got "\   131                               + repr(1 + len(args))   132         try:   133             value = self[key]   134         except KeyError:   135             if args:   136                 return args[0]   137             raise   138         del self[key]   139         return value   140     def popitem(self):   141         try:   142             k, v = self.iteritems().next()   143         except StopIteration:   144             raise KeyError, 'container is empty'   145         del self[k]   146         return (k, v)   147     def update(self, other=None, **kwargs):   148         # Make progressively weaker assumptions about "other"   149         if other is None:   150             pass   151         elif hasattr(other, 'iteritems'):  # iteritems saves memory and lookups   152             for k, v in other.iteritems():   153                 self[k] = v   154         elif hasattr(other, 'keys'):   155             for k in other.keys():   156                 self[k] = other[k]   157         else:   158             for k, v in other:   159                 self[k] = v   160         if kwargs:   161             self.update(kwargs)   162     def get(self, key, default=None):   163         try:   164             return self[key]   165         except KeyError:   166             return default   167     def __repr__(self):   168         return repr(dict(self.iteritems()))   169     def __cmp__(self, other):   170         if other is None:   171             return 1   172         if isinstance(other, DictMixin):   173             other = dict(other.iteritems())   174         return cmp(dict(self.iteritems()), other)   175     def __len__(self):   176         return len(self.keys())