Spaces:
Sleeping
Sleeping
import copy | |
class Dict(dict): | |
def __init__(__self, *args, **kwargs): | |
object.__setattr__(__self, '__parent', kwargs.pop('__parent', None)) | |
object.__setattr__(__self, '__key', kwargs.pop('__key', None)) | |
object.__setattr__(__self, '__frozen', False) | |
for arg in args: | |
if not arg: | |
continue | |
elif isinstance(arg, dict): | |
for key, val in arg.items(): | |
__self[key] = __self._hook(val) | |
elif isinstance(arg, tuple) and (not isinstance(arg[0], tuple)): | |
__self[arg[0]] = __self._hook(arg[1]) | |
else: | |
for key, val in iter(arg): | |
__self[key] = __self._hook(val) | |
for key, val in kwargs.items(): | |
__self[key] = __self._hook(val) | |
def __setattr__(self, name, value): | |
if hasattr(self.__class__, name): | |
raise AttributeError("'Dict' object attribute " | |
"'{0}' is read-only".format(name)) | |
else: | |
self[name] = value | |
def __setitem__(self, name, value): | |
isFrozen = (hasattr(self, '__frozen') and | |
object.__getattribute__(self, '__frozen')) | |
if isFrozen and name not in super(Dict, self).keys(): | |
raise KeyError(name) | |
super(Dict, self).__setitem__(name, value) | |
try: | |
p = object.__getattribute__(self, '__parent') | |
key = object.__getattribute__(self, '__key') | |
except AttributeError: | |
p = None | |
key = None | |
if p is not None: | |
p[key] = self | |
object.__delattr__(self, '__parent') | |
object.__delattr__(self, '__key') | |
def __add__(self, other): | |
if not self.keys(): | |
return other | |
else: | |
self_type = type(self).__name__ | |
other_type = type(other).__name__ | |
msg = "unsupported operand type(s) for +: '{}' and '{}'" | |
raise TypeError(msg.format(self_type, other_type)) | |
def _hook(cls, item): | |
if isinstance(item, dict): | |
return cls(item) | |
elif isinstance(item, (list, tuple)): | |
return type(item)(cls._hook(elem) for elem in item) | |
return item | |
def __getattr__(self, item): | |
return self.__getitem__(item) | |
def __missing__(self, name): | |
if object.__getattribute__(self, '__frozen'): | |
raise KeyError(name) | |
return self.__class__(__parent=self, __key=name) | |
def __delattr__(self, name): | |
del self[name] | |
def to_dict(self): | |
base = {} | |
for key, value in self.items(): | |
if isinstance(value, type(self)): | |
base[key] = value.to_dict() | |
elif isinstance(value, (list, tuple)): | |
base[key] = type(value)( | |
item.to_dict() if isinstance(item, type(self)) else | |
item for item in value) | |
else: | |
base[key] = value | |
return base | |
def copy(self): | |
return copy.copy(self) | |
def deepcopy(self): | |
return copy.deepcopy(self) | |
def __deepcopy__(self, memo): | |
other = self.__class__() | |
memo[id(self)] = other | |
for key, value in self.items(): | |
other[copy.deepcopy(key, memo)] = copy.deepcopy(value, memo) | |
return other | |
def update(self, *args, **kwargs): | |
other = {} | |
if args: | |
if len(args) > 1: | |
raise TypeError() | |
other.update(args[0]) | |
other.update(kwargs) | |
for k, v in other.items(): | |
if ((k not in self) or | |
(not isinstance(self[k], dict)) or | |
(not isinstance(v, dict))): | |
self[k] = v | |
else: | |
self[k].update(v) | |
def __getnewargs__(self): | |
return tuple(self.items()) | |
def __getstate__(self): | |
return self | |
def __setstate__(self, state): | |
self.update(state) | |
def __or__(self, other): | |
if not isinstance(other, (Dict, dict)): | |
return NotImplemented | |
new = Dict(self) | |
new.update(other) | |
return new | |
def __ror__(self, other): | |
if not isinstance(other, (Dict, dict)): | |
return NotImplemented | |
new = Dict(other) | |
new.update(self) | |
return new | |
def __ior__(self, other): | |
self.update(other) | |
return self | |
def setdefault(self, key, default=None): | |
if key in self: | |
return self[key] | |
else: | |
self[key] = default | |
return default | |
def freeze(self, shouldFreeze=True): | |
object.__setattr__(self, '__frozen', shouldFreeze) | |
for key, val in self.items(): | |
if isinstance(val, Dict): | |
val.freeze(shouldFreeze) | |
def unfreeze(self): | |
self.freeze(False) | |