2023-03-06 23:45:38 +00:00
|
|
|
from benedict.dicts.base import BaseDict
|
|
|
|
|
|
|
|
|
|
|
|
class KeyattrDict(BaseDict):
|
|
|
|
_keyattr_enabled = None
|
2023-03-22 00:21:40 +00:00
|
|
|
_keyattr_dynamic = None
|
2023-03-06 23:45:38 +00:00
|
|
|
|
|
|
|
def __init__(self, *args, **kwargs):
|
2023-03-08 23:51:13 +00:00
|
|
|
self._keyattr_enabled = kwargs.pop("keyattr_enabled", True)
|
2023-03-22 00:21:40 +00:00
|
|
|
self._keyattr_dynamic = kwargs.pop("keyattr_dynamic", False)
|
2023-03-06 23:45:38 +00:00
|
|
|
super().__init__(*args, **kwargs)
|
|
|
|
|
|
|
|
@property
|
|
|
|
def keyattr_enabled(self):
|
|
|
|
return self._keyattr_enabled
|
|
|
|
|
|
|
|
@keyattr_enabled.setter
|
|
|
|
def keyattr_enabled(self, value):
|
|
|
|
self._keyattr_enabled = value
|
|
|
|
|
2023-03-22 00:21:40 +00:00
|
|
|
@property
|
|
|
|
def keyattr_dynamic(self):
|
|
|
|
return self._keyattr_dynamic
|
|
|
|
|
|
|
|
@keyattr_dynamic.setter
|
|
|
|
def keyattr_dynamic(self, value):
|
|
|
|
self._keyattr_dynamic = value
|
|
|
|
|
2023-03-06 23:45:38 +00:00
|
|
|
def __getattr__(self, attr):
|
2023-03-22 00:21:40 +00:00
|
|
|
attr_message = f"{self.__class__.__name__!r} object has no attribute {attr!r}"
|
2023-03-06 23:45:38 +00:00
|
|
|
if not self._keyattr_enabled:
|
2023-03-22 00:21:40 +00:00
|
|
|
raise AttributeError(attr_message)
|
2023-03-06 23:45:38 +00:00
|
|
|
try:
|
|
|
|
return self.__getitem__(attr)
|
|
|
|
except KeyError:
|
2023-03-09 10:53:40 +00:00
|
|
|
if attr.startswith("_"):
|
2023-03-22 00:21:40 +00:00
|
|
|
raise AttributeError(attr_message) from None
|
|
|
|
if not self._keyattr_dynamic:
|
|
|
|
raise AttributeError(attr_message) from None
|
2023-03-06 23:45:38 +00:00
|
|
|
self.__setitem__(attr, {})
|
|
|
|
return self.__getitem__(attr)
|
|
|
|
|
|
|
|
def __setattr__(self, attr, value):
|
2023-03-22 00:21:40 +00:00
|
|
|
attr_message = f"{self.__class__.__name__!r} object has no attribute {attr!r}"
|
2023-03-06 23:45:38 +00:00
|
|
|
if attr in self:
|
|
|
|
# set existing key
|
|
|
|
if not self._keyattr_enabled:
|
2023-03-22 00:21:40 +00:00
|
|
|
raise AttributeError(attr_message)
|
2023-03-06 23:45:38 +00:00
|
|
|
self.__setitem__(attr, value)
|
|
|
|
elif hasattr(self.__class__, attr):
|
|
|
|
# set existing attr
|
|
|
|
super().__setattr__(attr, value)
|
|
|
|
else:
|
|
|
|
# set new key
|
|
|
|
if not self._keyattr_enabled:
|
2023-03-22 00:21:40 +00:00
|
|
|
raise AttributeError(attr_message)
|
2023-03-06 23:45:38 +00:00
|
|
|
self.__setitem__(attr, value)
|
2023-03-09 00:13:24 +00:00
|
|
|
|
|
|
|
def __setstate__(self, state):
|
|
|
|
super().__setstate__(state)
|
|
|
|
self._keyattr_enabled = state["_keyattr_enabled"]
|
2023-03-22 00:21:40 +00:00
|
|
|
self._keyattr_dynamic = state["_keyattr_dynamic"]
|