Files
MyManagingTools/src/core/Expando.py

74 lines
1.8 KiB
Python

class Expando:
"""
Readonly dynamic class that eases the access to attributes and sub attributes
It is initialized with a dict
You can then access the property using dot '.' (ex. obj.prop1.prop2)
"""
def __init__(self, props):
self._props = props
def __getattr__(self, item):
if item not in self._props:
raise AttributeError(item)
current = self._props[item]
return Expando(current) if isinstance(current, dict) else current
def __setitem__(self, key, value):
self._props[key] = value
def get(self, path):
"""
returns the value, from a string with represents the path
:param path:
:return:
"""
current = self._props
for attr in path.split("."):
if isinstance(current, list):
temp = []
for value in current:
if value and attr in value:
temp.append(value[attr])
current = temp
else:
if current is None or attr not in current:
return None
current = current[attr]
return current
def as_dict(self):
"""
Return the information as a dictionary
:return:
"""
return self._props.copy()
def to_dict(self, mappings: dict) -> dict:
return {prop_name: self.get(path) for path, prop_name in mappings.items() if prop_name is not None}
def __hasattr__(self, item):
return item in self._props
def __repr__(self):
if "key" in self._props:
return f"Expando(key={self._props["key"]})"
props_as_str = str(self._props)
if len(props_as_str) > 50:
props_as_str = props_as_str[:50] + "..."
return f"Expando({props_as_str})"
def __eq__(self, other):
if not isinstance(other, Expando):
return False
return self._props == other._props
def __hash__(self):
return hash(tuple(sorted(self._props.items())))