| 14 | |
| 15 | |
| 16 | class DotMap(MutableMapping, OrderedDict): |
| 17 | def __init__(self, *args, **kwargs): |
| 18 | self._map = OrderedDict() |
| 19 | self._dynamic = True |
| 20 | if kwargs: |
| 21 | if '_dynamic' in kwargs: |
| 22 | self._dynamic = kwargs['_dynamic'] |
| 23 | if args: |
| 24 | d = args[0] |
| 25 | # for recursive assignment handling |
| 26 | trackedIDs = {id(d): self} |
| 27 | if isinstance(d, dict): |
| 28 | for k,v in self.__call_items(d): |
| 29 | if isinstance(v, dict): |
| 30 | if id(v) in trackedIDs: |
| 31 | v = trackedIDs[id(v)] |
| 32 | else: |
| 33 | v = self.__class__(v, _dynamic=self._dynamic) |
| 34 | trackedIDs[id(v)] = v |
| 35 | if type(v) is list: |
| 36 | l = [] |
| 37 | for i in v: |
| 38 | n = i |
| 39 | if isinstance(i, dict): |
| 40 | n = self.__class__(i, _dynamic=self._dynamic) |
| 41 | l.append(n) |
| 42 | v = l |
| 43 | self._map[k] = v |
| 44 | if kwargs: |
| 45 | for k,v in self.__call_items(kwargs): |
| 46 | if k is not '_dynamic': |
| 47 | self._map[k] = v |
| 48 | |
| 49 | def __call_items(self, obj): |
| 50 | if hasattr(obj, 'iteritems') and ismethod(getattr(obj, 'iteritems')): |
| 51 | return obj.iteritems() |
| 52 | else: |
| 53 | return obj.items() |
| 54 | |
| 55 | def items(self): |
| 56 | return self.iteritems() |
| 57 | |
| 58 | def iteritems(self): |
| 59 | return self.__call_items(self._map) |
| 60 | |
| 61 | def __iter__(self): |
| 62 | return self._map.__iter__() |
| 63 | |
| 64 | def next(self): |
| 65 | return self._map.next() |
| 66 | |
| 67 | def __setitem__(self, k, v): |
| 68 | self._map[k] = v |
| 69 | def __getitem__(self, k): |
| 70 | if k not in self._map and self._dynamic and k != '_ipython_canary_method_should_not_exist_': |
| 71 | # automatically extend to new DotMap |
| 72 | self[k] = self.__class__() |
| 73 | return self._map[k] |
no outgoing calls
searching dependent graphs…