1 # Copyright (c) 2005 The Regents of The University of Michigan
4 # Redistribution and use in source and binary forms, with or without
5 # modification, are permitted provided that the following conditions are
6 # met: redistributions of source code must retain the above copyright
7 # notice, this list of conditions and the following disclaimer;
8 # redistributions in binary form must reproduce the above copyright
9 # notice, this list of conditions and the following disclaimer in the
10 # documentation and/or other materials provided with the distribution;
11 # neither the name of the copyright holders nor the names of its
12 # contributors may be used to endorse or promote products derived from
13 # this software without specific prior written permission.
15 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 # Authors: Nathan Binkert
29 __all__
= [ 'multidict' ]
31 class multidict(object):
32 def __init__(self
, parent
= {}, **kwargs
):
33 self
.local
= dict(**kwargs
)
38 return str(dict(self
.items()))
41 return `
dict(self
.items())`
43 def __contains__(self
, key
):
44 return self
.local
.has_key(key
) or self
.parent
.has_key(key
)
46 def __delitem__(self
, key
):
50 if key
in self
.parent
:
51 self
.deleted
[key
] = True
55 def __setitem__(self
, key
, value
):
56 self
.deleted
.pop(key
, False)
57 self
.local
[key
] = value
59 def __getitem__(self
, key
):
61 return self
.local
[key
]
63 if not self
.deleted
.get(key
, False) and key
in self
.parent
:
64 return self
.parent
[key
]
69 return len(self
.local
) + len(self
.parent
)
72 for key
,value
in self
.local
.items():
76 for key
,value
in self
.parent
.next():
77 if key
not in self
.local
and key
not in self
.deleted
:
80 def has_key(self
, key
):
84 for item
in self
.next():
88 return [ item
for item
in self
.next() ]
91 for key
,value
in self
.next():
95 return [ key
for key
,value
in self
.next() ]
98 for key
,value
in self
.next():
102 return [ value
for key
,value
in self
.next() ]
104 def get(self
, key
, default
=None):
110 def setdefault(self
, key
, default
):
114 self
.deleted
.pop(key
, False)
115 self
.local
[key
] = default
119 print 'multidict dump'
121 while isinstance(node
, multidict
):
122 print ' ', node
.local
125 def _dumpkey(self
, key
):
128 while isinstance(node
, multidict
):
129 if key
in node
.local
:
130 values
.append(node
.local
[key
])
134 if __name__
== '__main__':
136 test2
= multidict(test1
)
137 test3
= multidict(test2
)
138 test4
= multidict(test3
)
140 test1
['a'] = 'test1_a'
141 test1
['b'] = 'test1_b'
142 test1
['c'] = 'test1_c'
143 test1
['d'] = 'test1_d'
144 test1
['e'] = 'test1_e'
146 test2
['a'] = 'test2_a'
148 test2
['c'] = 'test2_c'
151 test2
.setdefault('f', multidict
)
153 print 'test1>', test1
.items()
154 print 'test2>', test2
.items()
167 for key
in test2
.iterkeys():
170 test2
.get('g', 'foo')
172 test2
.get('b', 'bar')
173 test2
.setdefault('b', 'blah')
180 test3
['a'] = [ 0, 1, 2, 3 ]