import six # coding=utf-8 class DictProxy(object): store = None def __init__(self, d): self.Dict = d super(DictProxy, self).__init__() if self.store not in self.Dict or not self.Dict[self.store]: self.Dict[self.store] = self.setup_defaults() self.save() self.__initialized = True def __getattr__(self, name): if name in self.Dict[self.store]: return self.Dict[self.store][name] return getattr(super(DictProxy, self), name) def __setattr__(self, name, value): if '_DictProxy__initialized' not in self.__dict__: # this test allows attributes to be set in the __init__ method return object.__setattr__(self, name, value) elif name in self.__dict__: # any normal attributes are handled normally object.__setattr__(self, name, value) else: if name in self.Dict[self.store]: self.Dict[self.store][name] = value return object.__setattr__(self, name, value) def __cmp__(self, d): return cmp(self.Dict[self.store], d) def __contains__(self, item): return item in self.Dict[self.store] def __setitem__(self, key, item): self.Dict[self.store][key] = item self.Dict.Save() def __iter__(self): return iter(self.Dict[self.store]) def __getitem__(self, key): if key in self.Dict[self.store]: return self.Dict[self.store][key] def __repr__(self): return repr(self.Dict[self.store]) def __str__(self): return str(self.Dict[self.store]) def __len__(self): return len(list(self.Dict[self.store].keys())) def __delitem__(self, key): del self.Dict[self.store][key] def save(self): self.Dict.Save() def clear(self): del self.Dict[self.store] return None def copy(self): return self.Dict[self.store].copy() def has_key(self, k): return k in self.Dict[self.store] def pop(self, k, d=None): return self.Dict[self.store].pop(k, d) def update(self, *args, **kwargs): return self.Dict[self.store].update(*args, **kwargs) def keys(self): return list(self.Dict[self.store].keys()) def values(self): return list(self.Dict[self.store].values()) def items(self): return list(self.Dict[self.store].items()) def __unicode__(self): return six.text_type(repr(self.Dict[self.store])) def setup_defaults(self): raise NotImplementedError class Dicked(object): """ mirrors a dictionary; readonly """ _entries = None def __init__(self, **entries): self._entries = entries or None for key, value in six.iteritems(entries): self.__dict__[key] = (Dicked(**value) if isinstance(value, dict) else value) def has(self, key): return self._entries is not None and key in self._entries def get(self, key, default=None): return self._entries.get(key, default) if self._entries else default def __repr__(self): return str(self) def __unicode__(self): return six.text_type(self.__digged__) def __str__(self): return str(self.__digged__) def __lt__(self, d): return self._entries < d def __le__(self, d): return self._entries <= d def __eq__(self, d): if d is None and not self._entries: return True return self._entries == d def __ne__(self, d): return self._entries != d def __gt__(self, d): return self._entries > d def __ge__(self, d): return self._entries >= d def __getattr__(self, name): # fixme: this might be wildly stupid; maybe implement stuff like .iteritems() directly return getattr(self._entries, name, Dicked()) @property def __digged__(self): return {key: value for key, value in six.iteritems(self.__dict__) if key != "_entries"} def __len__(self): return len(self.__digged__) def __nonzero__(self): return bool(self.__digged__) def __iter__(self): return iter(self.__digged__) def __hash__(self): return hash(self.__digged__) def __getitem__(self, name): if name in self._entries: return getattr(self, name) raise KeyError(name)