1
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
3
# Copyright (c) 2012, Peter Levi <peterlevi@peterlevi.com>
4
# This program is free software: you can redistribute it and/or modify it
5
# under the terms of the GNU General Public License version 3, as published
6
# by the Free Software Foundation.
8
# This program is distributed in the hope that it will be useful, but
9
# WITHOUT ANY WARRANTY; without even the implied warranties of
10
# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11
# PURPOSE. See the GNU General Public License for more details.
13
# You should have received a copy of the GNU General Public License along
14
# with this program. If not, see <http://www.gnu.org/licenses/>.
17
from collections import defaultdict
21
class AttrDict(defaultdict):
24
if isinstance(v, AttrDict):
26
elif isinstance(v, dict):
28
elif isinstance(v, (list, tuple)):
29
r = map(AttrDict.converted, v)
30
return tuple(r) if isinstance(v, tuple) else r
35
if hasattr(arg, 'iteritems'):
36
self.merge(arg.iteritems())
39
self[k] = AttrDict.converted(v)
42
return json.loads(json.dumps(self))
44
def __init__(self, *args, **kwargs):
45
super(AttrDict, self).__init__(AttrDict)
49
raise TypeError("AttrDict expected at most 1 argument that is a map, got %i" % len(args))
52
def __setitem__(self, k, v):
53
return super(AttrDict, self).__setitem__(k, AttrDict.converted(v))
55
__getattr__ = defaultdict.__getitem__
56
__setattr__ = __setitem__
60
if __name__ == "__main__":
61
a = AttrDict({'a': {'b':1}})
62
assert not bool(a.deep.inside)
70
assert a["x"]["y"]["z"] == 1
72
b = AttrDict(x=1, y=2)
73
assert not bool(b.deep.inside)
79
assert not bool(b.c.dredrefre)