mirror of https://gitee.com/anolis/sysom.git
186 lines
5.5 KiB
Python
186 lines
5.5 KiB
Python
# -*- coding: utf-8 -*- #
|
|
"""
|
|
Time 2023/03/09 13:58
|
|
Author: mingfeng (SunnyQjm)
|
|
Email mfeng@linux.alibaba.com
|
|
File __init__.py.py
|
|
Description:
|
|
"""
|
|
import copy
|
|
from typing import Optional
|
|
|
|
|
|
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))
|
|
|
|
@classmethod
|
|
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 get_multi(self, key_str: str) -> Optional[any]:
|
|
try:
|
|
keys = key_str.split(".")
|
|
res = self
|
|
for key in keys:
|
|
res = res.get(key)
|
|
except Exception as _:
|
|
return None
|
|
return res
|
|
|
|
def set_multi(self, key_str: str, value: any):
|
|
keys = key_str.split(".")
|
|
res = self
|
|
for i in range(len(keys) - 1):
|
|
res = res[keys[i]]
|
|
res[keys[-1]] = value
|
|
|
|
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)
|