Doa-doa's picture
Upload folder using huggingface_hub
72268ee
# =========================================
# IMPORT
# --------------------------------------
import rootpath
rootpath.append()
import collections
import attributedict.compat as compat
# =========================================
# CONSTANTS
# --------------------------------------
DEFAULT_RESERVED_KEY_PREFIX = '__'
DEFAULT_RESERVED_KEY_SUFFIX = None
# =========================================
# CLASSES
# --------------------------------------
class AttributeDict(dict):
"""
:class:`~attributedict.collections.AttributeDict` is a seamlessly extended dictionary object (subclass of `dict`),
with access to additional attribute get/set/delete of key/values.
@example:
data = AttributeDict({'foo': {'bar': [1, 2, 3]}})
data.foo # => `{'bar': [1, 2, 3]}}`
data.foo.bar # => `[1, 2, 3]`
data.foo = {'baz': True}
data.foo = # => `{'baz': True}`
del data.foo
"""
def __init__(self, entries = {}):
entries = entries or {}
entries = self._reject_reserved_keys(entries)
super(AttributeDict, self).__init__(entries)
self.update(entries)
def _refresh(self):
# HACK
#
# to make object encoding (e.g. `json` work), call `dict` constructor with updated data.
#
# it is terrible language design that this is the only way. >:/
#
# @see https://stackoverflow.com/questions/23088565/make-a-custom-class-json-serializable
# @see https://stackoverflow.com/questions/2144988/python-multiple-calls-to-init-on-the-same-instance
#
# print('_refresh')
dict.__init__(self, self.__dict__)
def _reject_reserved_keys(self, object = {}):
# NOTE:
# tricky to override on the instance, because only special attribute `self__dict__` is not causing
# recursive calls to `self.__getattr__`. =S
reserved_key_prefix = DEFAULT_RESERVED_KEY_PREFIX
reserved_key_suffix = DEFAULT_RESERVED_KEY_SUFFIX
if isinstance(object, dict):
for key, value in list(object.items()):
is_reserved = False
if len(reserved_key_prefix or ''):
is_reserved = key.startswith(reserved_key_prefix)
if len(reserved_key_suffix or ''):
is_reserved = is_reserved or key.startswith(reserved_key_suffix)
if is_reserved:
del object[key]
else:
object[key] = self._reject_reserved_keys(object[key])
return object
def update(self, entries = {}, *args, **kwargs):
"""
Update dictionary.
@example:
object.update({'foo': {'bar': 1}})
"""
if isinstance(entries, dict):
entries = self._reject_reserved_keys(entries)
for key, value in dict(entries, *args, **kwargs).items():
if isinstance(value, dict):
self.__dict__[key] = AttributeDict(value)
else:
self.__dict__[key] = value
self._refresh()
def keys(self):
return self.__dict__.keys()
def values(self):
return self.__dict__.values()
def items(self, *args, **kwargs):
return self.__dict__.items(*args, **kwargs)
def iterkeys(self, *args, **kwargs):
self.__dict__.iterkeys(*args, **kwargs)
def itervalues(self, *args, **kwargs):
self.__dict__.itervalues(*args, **kwargs)
def iteritems(self, *args, **kwargs):
self.__dict__.items(*args, **kwargs)
def get(self, key, default = None):
result = self.__dict__.get(key, default)
return result
def pop(self, key, value = None):
result = self.__dict__.pop(key, value)
self._refresh()
return result
def copy(self):
return type(self)(self)
def setdefault(self, key, default = None):
result = self.__dict__.setdefault(key, default)
self._refresh()
return result
def __getitem__(self, key):
"""
Provides `dict` style property access to dictionary key-values.
@example:
value = object['key']
# ignored
object['__key__']
"""
result = self.__dict__.__getitem__(key)
self._refresh()
return result
def __setitem__(self, key, value):
"""
Provides `dict` style property assignment to dictionary key-values.
@example:
object['key'] = value
# ignored
object['__key__'] = value
"""
if isinstance(value, dict):
value = AttributeDict(value)
result = self.__dict__.__setitem__(key, value)
self._refresh()
return result
def __delitem__(self, key):
"""
Provides `dict` style property deletion to dictionary key-values.
@example:
del object['key']
# ignored
del object['__key__']
"""
result = self.__dict__.__delitem__(key)
self._refresh()
return result
def __getattr__(self, key):
"""
Provides `object` style attribute access to dictionary key-values.
@example:
value = object.key
# ignored
object.__key__
"""
try:
return self.__getitem__(key)
except Exception as error:
raise AttributeError(error)
def __setattr__(self, key, value):
"""
Provides `object` style attribute assignment to dictionary key-values.
@example:
object.key = value
# ignored
object.__key__ = value
"""
try:
return self.__setitem__(key, value)
except Exception as error:
raise AttributeError(error)
def __delattr__(self, key):
"""
Provides `object` style attribute deletion to dictionary key-values.
@example:
del object.key
# ignored
del object.__key__
"""
try:
return self.__delitem__(key)
except Exception as error:
raise AttributeError(error)
def __str__(self):
"""
String value of the dictionary instance.
"""
return str(self.__dict__)
def __repr__(self):
"""
String representation of the dictionary instance.
"""
return repr(self.__dict__)
def __dir__(self):
return dir(type(self)) + list(self.__dict__.keys())
def __iter__(self):
"""
Iterate over dictionary key/values.
"""
return iter(self.__dict__.keys())
def __len__(self):
"""
Get number of items.
"""
return len(self.__dict__.keys())
def __contains__(self, key):
"""
Check if key exists.
"""
return self.__dict__.__contains__(key)
def __reduce__(self):
"""
Return state information for pickling.
"""
return self.__dict__.__reduce__()
def __eq__(self, other):
"""
Check dictionary is equal to another provided dictionary.
"""
return self.__dict__.__eq__(other)
def __ne__(self, other):
"""
Check dictionary is inequal to another provided dictionary.
"""
return self.__dict__.__ne__(other)
def to_dict(self):
return self.__class__.dict(self.__dict__)
@classmethod
def fromkeys(klass, keys, value = None):
return AttributeDict(dict.fromkeys((key for key in keys), value))
@classmethod
def dict(klass, _dict = {}):
if _dict is None:
return None
new_dict = {}
for key, value in _dict.items():
if isinstance(value, AttributeDict):
new_dict[key] = AttributeDict.to_dict(value)
else:
new_dict[key] = value
return new_dict
# =========================================
# EXPORT
# --------------------------------------
attributedict = AttributeDict
attrdict = AttributeDict
__all__ = [
'AttributeDict',
'attributedict',
'attrdict',
]
# =========================================
# MAIN
# --------------------------------------
if __name__ == '__main__':
data = {
'a': {
'b': {
'c': [1, 2, 3]
}
}
}
object = AttributeDict(data)
print('object = AttributeDict({0})\n'.format(data))
print('object\n\n\t{0}\n'.format(object))
print('object.a\n\n\t{0}\n'.format(object.a))
print('object.a.b\n\n\t{0}\n'.format(object.a.b))
print('object.a.b.c\n\n\t{0}\n'.format(object.a.b.c))