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