From 6aa3ddae4f09daee07aa50c1b2ba8344a17ff198 Mon Sep 17 00:00:00 2001 From: Sebastian Goscik Date: Fri, 12 Aug 2016 11:33:31 +0100 Subject: [PATCH] types: Added obj_dict obj_dict is a a dictionary that can have its entries accessed either via the standard `[some_key]` method or via the obj_dict's attributes `obj_dict.some_key`. This comes is very useful when needing to use `ConfigurationPoints` outside of a `Configuration` object --- wlauto/utils/types.py | 66 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 65 insertions(+), 1 deletion(-) 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