0001"""
0002**Deprecated** (13 Aug 2006)
0003
0004Layers multiple dictionaries.
0005
0006Nested dictionaries can be traversed, with each dictionary shadowing
0007the previous dictionaries. So for example:
0008
0009 >>> d = NestedDict([{'foo': 'bar'}])
0010 >>> d['foo']
0011 'bar'
0012 >>> d2 = d.clone(add_dict={'foo': 'bar2'})
0013 >>> d2['foo']
0014 'bar2'
0015 >>> d2.getlist('foo')
0016 ['bar2', 'bar']
0017
0018This works for deeply nested dictionaries, not just at the top level;
0019each nested dictionary gets wrapped in a NestedDict as well.
0020"""
0021
0022
0023import warnings
0024warnings.warn('initools.nested is not supported or recommended for use.',
0025 DeprecationWarning)
0026
0027from UserDict import DictMixin, UserDict
0028
0029class NestedDict(DictMixin):
0030
0031 def __init__(self, configs=None, mutable=True, nest=True):
0032 if configs is None:
0033 configs = [{}]
0034 assert isinstance(configs, (list, tuple)), (
0035 "The configs must be a list or tuple, not: %r"
0036 % configs)
0037 self.configs = configs
0038 self.mutable = mutable
0039 self.nest = nest
0040
0041 def __getitem__(self, key):
0042 results = self.raw_get(key)
0043 if not results:
0044 raise KeyError, "Key not found: %r" % key
0045 return self._convert_single(key, results)
0046
0047 def add_config(self, config, position=0):
0048 assert not isinstance(config, (str, unicode)), (
0049 "Bad configuration (not a mapping): %r" % config)
0050 if position is None:
0051 self.configs.append(config)
0052 else:
0053 self.configs.insert(position, config)
0054
0055 def set_configs(self, new_configs):
0056 self.configs[:] = []
0057 for config in new_configs:
0058 self.add_config(config, None)
0059
0060 def raw_get(self, key, add_inherited=True):
0061 results = []
0062 if add_inherited:
0063 all_configs = self.configs
0064 else:
0065 all_configs = [self.configs[-1]]
0066 for config in all_configs:
0067 if key in config:
0068 if isinstance(config, (str, unicode)):
0069 print [key, config, all_configs, self.configs]
0070 results.append(config[key])
0071 return results
0072
0073 def getlist(self, key, add_inherited=True):
0074 results = self.raw_get(key, add_inherited=add_inherited)
0075 converted = []
0076 for result_set in results:
0077 if not isinstance(result_set, (list, tuple)):
0078 result_set = [result_set]
0079 converted.extend(self._convert_many(key, result_set))
0080 return converted
0081
0082 def _convert_single(self, key, value_list):
0083 if (not self.nest
0084 or not isinstance(value_list[0],
0085 (dict, DictMixin, UserDict))):
0086
0087 return value_list[0]
0088 elif len(value_list) == 1 and self.mutable:
0089 return value_list[0]
0090 else:
0091 return self.__class__(
0092 value_list, mutable=self.mutable, nest=True)
0093
0094 def _convert_many(self, key, value_list):
0095 return [self._convert_single(key, [v]) for v in value_list]
0096
0097 def __setitem__(self, key, value):
0098 if self.mutable:
0099 self.configs[0][key] = value
0100 else:
0101 raise KeyError, (
0102 "Dictionary is read-only")
0103
0104 def __delitem__(self, key):
0105 if not self.mutable:
0106 raise KeyError, (
0107 "Dictionary is read-only")
0108 if self.configs[0].has_key(key):
0109 del self.configs[0][key]
0110 elif self.has_key(key):
0111 raise KeyError, (
0112 "You cannot delete the key %r, as it belongs to the "
0113 "a master configuration %r"
0114 % (key, self.master))
0115 else:
0116 raise KeyError, (
0117 "Key does not exist: %r" % key)
0118
0119 def keys(self):
0120 return list(self)
0121
0122 def __contains__(self, key):
0123 for config in self.configs:
0124 if config.has_key(key):
0125 return True
0126 return False
0127
0128 def has_key(self, key):
0129 return key in self
0130
0131 def __iter__(self):
0132 used = {}
0133 for config in self.configs:
0134 for key in config:
0135 if key in used:
0136 continue
0137 used[key] = None
0138 yield key
0139
0140 _clone_sentry = []
0141
0142 def clone(self, add_dict=None, mutable=_clone_sentry,
0143 nest=_clone_sentry):
0144 if mutable is self._clone_sentry:
0145 mutable = self.mutable
0146 if nest is self._clone_sentry:
0147 nest = self.nest
0148 new = self.configs[:]
0149 if add_dict is not None:
0150 new.insert(0, add_dict)
0151 else:
0152 new.insert(0, {})
0153 return self.__class__(new, mutable=mutable, nest=nest)
0154
0155 def copy(self):
0156 return dict(self.iteritems())
0157
0158 def __eq__(self, other):
0159 if other is None:
0160 return False
0161 if (not hasattr(other, 'keys')
0162 or not hasattr(other, '__getitem__')):
0163 return False
0164 for key in other:
0165 if not key in self:
0166 return False
0167 for name, value in self.iteritems():
0168 if other[name] != value:
0169 return False
0170 return True
0171
0172 def __cmp__(self, other):
0173 return not self.__eq__(other)
0174
0175 def __repr__(self):
0176 return '<%s %r>' % (self.__class__.__name__,
0177 dict(self.iteritems()))