+++ /dev/null
-"""A more or less complete user-defined wrapper around dictionary objects."""\r
-\r
-class UserDict:\r
- def __init__(self, dict=None, **kwargs):\r
- self.data = {}\r
- if dict is not None:\r
- self.update(dict)\r
- if len(kwargs):\r
- self.update(kwargs)\r
- def __repr__(self): return repr(self.data)\r
- def __cmp__(self, dict):\r
- if isinstance(dict, UserDict):\r
- return cmp(self.data, dict.data)\r
- else:\r
- return cmp(self.data, dict)\r
- __hash__ = None # Avoid Py3k warning\r
- def __len__(self): return len(self.data)\r
- def __getitem__(self, key):\r
- if key in self.data:\r
- return self.data[key]\r
- if hasattr(self.__class__, "__missing__"):\r
- return self.__class__.__missing__(self, key)\r
- raise KeyError(key)\r
- def __setitem__(self, key, item): self.data[key] = item\r
- def __delitem__(self, key): del self.data[key]\r
- def clear(self): self.data.clear()\r
- def copy(self):\r
- if self.__class__ is UserDict:\r
- return UserDict(self.data.copy())\r
- import copy\r
- data = self.data\r
- try:\r
- self.data = {}\r
- c = copy.copy(self)\r
- finally:\r
- self.data = data\r
- c.update(self)\r
- return c\r
- def keys(self): return self.data.keys()\r
- def items(self): return self.data.items()\r
- def iteritems(self): return self.data.iteritems()\r
- def iterkeys(self): return self.data.iterkeys()\r
- def itervalues(self): return self.data.itervalues()\r
- def values(self): return self.data.values()\r
- def has_key(self, key): return key in self.data\r
- def update(self, dict=None, **kwargs):\r
- if dict is None:\r
- pass\r
- elif isinstance(dict, UserDict):\r
- self.data.update(dict.data)\r
- elif isinstance(dict, type({})) or not hasattr(dict, 'items'):\r
- self.data.update(dict)\r
- else:\r
- for k, v in dict.items():\r
- self[k] = v\r
- if len(kwargs):\r
- self.data.update(kwargs)\r
- def get(self, key, failobj=None):\r
- if key not in self:\r
- return failobj\r
- return self[key]\r
- def setdefault(self, key, failobj=None):\r
- if key not in self:\r
- self[key] = failobj\r
- return self[key]\r
- def pop(self, key, *args):\r
- return self.data.pop(key, *args)\r
- def popitem(self):\r
- return self.data.popitem()\r
- def __contains__(self, key):\r
- return key in self.data\r
- @classmethod\r
- def fromkeys(cls, iterable, value=None):\r
- d = cls()\r
- for key in iterable:\r
- d[key] = value\r
- return d\r
-\r
-class IterableUserDict(UserDict):\r
- def __iter__(self):\r
- return iter(self.data)\r
-\r
-import _abcoll\r
-_abcoll.MutableMapping.register(IterableUserDict)\r
-\r
-\r
-class DictMixin:\r
- # Mixin defining all dictionary methods for classes that already have\r
- # a minimum dictionary interface including getitem, setitem, delitem,\r
- # and keys. Without knowledge of the subclass constructor, the mixin\r
- # does not define __init__() or copy(). In addition to the four base\r
- # methods, progressively more efficiency comes with defining\r
- # __contains__(), __iter__(), and iteritems().\r
-\r
- # second level definitions support higher levels\r
- def __iter__(self):\r
- for k in self.keys():\r
- yield k\r
- def has_key(self, key):\r
- try:\r
- self[key]\r
- except KeyError:\r
- return False\r
- return True\r
- def __contains__(self, key):\r
- return self.has_key(key)\r
-\r
- # third level takes advantage of second level definitions\r
- def iteritems(self):\r
- for k in self:\r
- yield (k, self[k])\r
- def iterkeys(self):\r
- return self.__iter__()\r
-\r
- # fourth level uses definitions from lower levels\r
- def itervalues(self):\r
- for _, v in self.iteritems():\r
- yield v\r
- def values(self):\r
- return [v for _, v in self.iteritems()]\r
- def items(self):\r
- return list(self.iteritems())\r
- def clear(self):\r
- for key in self.keys():\r
- del self[key]\r
- def setdefault(self, key, default=None):\r
- try:\r
- return self[key]\r
- except KeyError:\r
- self[key] = default\r
- return default\r
- def pop(self, key, *args):\r
- if len(args) > 1:\r
- raise TypeError, "pop expected at most 2 arguments, got "\\r
- + repr(1 + len(args))\r
- try:\r
- value = self[key]\r
- except KeyError:\r
- if args:\r
- return args[0]\r
- raise\r
- del self[key]\r
- return value\r
- def popitem(self):\r
- try:\r
- k, v = self.iteritems().next()\r
- except StopIteration:\r
- raise KeyError, 'container is empty'\r
- del self[k]\r
- return (k, v)\r
- def update(self, other=None, **kwargs):\r
- # Make progressively weaker assumptions about "other"\r
- if other is None:\r
- pass\r
- elif hasattr(other, 'iteritems'): # iteritems saves memory and lookups\r
- for k, v in other.iteritems():\r
- self[k] = v\r
- elif hasattr(other, 'keys'):\r
- for k in other.keys():\r
- self[k] = other[k]\r
- else:\r
- for k, v in other:\r
- self[k] = v\r
- if kwargs:\r
- self.update(kwargs)\r
- def get(self, key, default=None):\r
- try:\r
- return self[key]\r
- except KeyError:\r
- return default\r
- def __repr__(self):\r
- return repr(dict(self.iteritems()))\r
- def __cmp__(self, other):\r
- if other is None:\r
- return 1\r
- if isinstance(other, DictMixin):\r
- other = dict(other.iteritems())\r
- return cmp(dict(self.iteritems()), other)\r
- def __len__(self):\r
- return len(self.keys())\r