diff --git a/wlauto/utils/types.py b/wlauto/utils/types.py index 863a680f..94f257f2 100644 --- a/wlauto/utils/types.py +++ b/wlauto/utils/types.py @@ -30,7 +30,7 @@ import re import math import shlex from bisect import insort -from collections import defaultdict +from collections import defaultdict, MutableMapping from copy import copy from wlauto.utils.misc import isiterable, to_identifier @@ -402,3 +402,67 @@ class ID(str): def merge_into(self, other): return '_'.join(other, self) + + +class obj_dict(MutableMapping): + """ + An object that behaves like a dict but each dict entry can also be accesed + as an attribute. + + :param not_in_dict: A list of keys that can only be accessed as attributes + """ + + def __init__(self, not_in_dict=None, values={}): + self.__dict__['not_in_dict'] = not_in_dict if not_in_dict is not None else [] + self.__dict__['dict'] = dict(values) + + def __getitem__(self, key): + if key in self.not_in_dict: + msg = '"{}" is in the list keys that can only be accessed as attributes' + raise KeyError(msg.format(key)) + return self.__dict__['dict'][key] + + def __setitem__(self, key, value): + self.__dict__['dict'][key] = value + + def __delitem__(self, key): + del self.__dict__['dict'][key] + + def __len__(self): + return sum(1 for _ in self) + + def __iter__(self): + for key in self.__dict__['dict']: + if key not in self.__dict__['not_in_dict']: + yield key + + def __repr__(self): + return repr(dict(self)) + + def __str__(self): + return str(dict(self)) + + def __setattr__(self, name, value): + self.__dict__['dict'][name] = value + + def __delattr__(self, name): + if name in self: + del self.__dict__['dict'][name] + else: + raise AttributeError("No such attribute: " + name) + + def __getattr__(self, name): + if name in self.__dict__['dict']: + return self.__dict__['dict'][name] + else: + raise AttributeError("No such attribute: " + name) + + def to_pod(self): + return self.__dict__.copy() + + @staticmethod + def from_pod(pod): + instance = ObjDict() + for k, v in pod.iteritems(): + instance[k] = v + return instance