multidict.py revision 5467:6d9df90d70d7
1# Copyright (c) 2005 The Regents of The University of Michigan 2# All rights reserved. 3# 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. 14# 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. 26# 27# Authors: Nathan Binkert 28 29__all__ = [ 'multidict' ] 30 31class multidict(object): 32 def __init__(self, parent = {}, **kwargs): 33 self.local = dict(**kwargs) 34 self.parent = parent 35 self.deleted = {} 36 37 def __str__(self): 38 return str(dict(self.items())) 39 40 def __repr__(self): 41 return `dict(self.items())` 42 43 def __contains__(self, key): 44 return self.local.has_key(key) or self.parent.has_key(key) 45 46 def __delitem__(self, key): 47 try: 48 del self.local[key] 49 except KeyError, e: 50 if key in self.parent: 51 self.deleted[key] = True 52 else: 53 raise KeyError, e 54 55 def __setitem__(self, key, value): 56 self.deleted.pop(key, False) 57 self.local[key] = value 58 59 def __getitem__(self, key): 60 try: 61 return self.local[key] 62 except KeyError, e: 63 if not self.deleted.get(key, False) and key in self.parent: 64 return self.parent[key] 65 else: 66 raise KeyError, e 67 68 def __len__(self): 69 return len(self.local) + len(self.parent) 70 71 def next(self): 72 for key,value in self.local.items(): 73 yield key,value 74 75 if self.parent: 76 for key,value in self.parent.next(): 77 if key not in self.local and key not in self.deleted: 78 yield key,value 79 80 def has_key(self, key): 81 return key in self 82 83 def iteritems(self): 84 for item in self.next(): 85 yield item 86 87 def items(self): 88 return [ item for item in self.next() ] 89 90 def iterkeys(self): 91 for key,value in self.next(): 92 yield key 93 94 def keys(self): 95 return [ key for key,value in self.next() ] 96 97 def itervalues(self): 98 for key,value in self.next(): 99 yield value 100 101 def values(self): 102 return [ value for key,value in self.next() ] 103 104 def get(self, key, default=None): 105 try: 106 return self[key] 107 except KeyError, e: 108 return default 109 110 def setdefault(self, key, default): 111 try: 112 return self[key] 113 except KeyError: 114 self.deleted.pop(key, False) 115 self.local[key] = default 116 return default 117 118 def _dump(self): 119 print 'multidict dump' 120 node = self 121 while isinstance(node, multidict): 122 print ' ', node.local 123 node = node.parent 124 125 def _dumpkey(self, key): 126 values = [] 127 node = self 128 while isinstance(node, multidict): 129 if key in node.local: 130 values.append(node.local[key]) 131 node = node.parent 132 print key, values 133 134if __name__ == '__main__': 135 test1 = multidict() 136 test2 = multidict(test1) 137 test3 = multidict(test2) 138 test4 = multidict(test3) 139 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' 145 146 test2['a'] = 'test2_a' 147 del test2['b'] 148 test2['c'] = 'test2_c' 149 del test1['a'] 150 151 test2.setdefault('f', multidict) 152 153 print 'test1>', test1.items() 154 print 'test2>', test2.items() 155 #print test1['a'] 156 print test1['b'] 157 print test1['c'] 158 print test1['d'] 159 print test1['e'] 160 161 print test2['a'] 162 #print test2['b'] 163 print test2['c'] 164 print test2['d'] 165 print test2['e'] 166 167 for key in test2.iterkeys(): 168 print key 169 170 test2.get('g', 'foo') 171 #test2.get('b') 172 test2.get('b', 'bar') 173 test2.setdefault('b', 'blah') 174 print test1 175 print test2 176 print `test2` 177 178 print len(test2) 179 180 test3['a'] = [ 0, 1, 2, 3 ] 181 182 print test4 183