multidict.py revision 13709:dd6b7ac5801f
112841Sgabeblack@google.com# Copyright (c) 2005 The Regents of The University of Michigan 212841Sgabeblack@google.com# All rights reserved. 312841Sgabeblack@google.com# 412841Sgabeblack@google.com# Redistribution and use in source and binary forms, with or without 512841Sgabeblack@google.com# modification, are permitted provided that the following conditions are 612841Sgabeblack@google.com# met: redistributions of source code must retain the above copyright 712841Sgabeblack@google.com# notice, this list of conditions and the following disclaimer; 812841Sgabeblack@google.com# redistributions in binary form must reproduce the above copyright 912841Sgabeblack@google.com# notice, this list of conditions and the following disclaimer in the 1012841Sgabeblack@google.com# documentation and/or other materials provided with the distribution; 1112841Sgabeblack@google.com# neither the name of the copyright holders nor the names of its 1212841Sgabeblack@google.com# contributors may be used to endorse or promote products derived from 1312841Sgabeblack@google.com# this software without specific prior written permission. 1412841Sgabeblack@google.com# 1512841Sgabeblack@google.com# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1612841Sgabeblack@google.com# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1712841Sgabeblack@google.com# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1812841Sgabeblack@google.com# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1912841Sgabeblack@google.com# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2012841Sgabeblack@google.com# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2112841Sgabeblack@google.com# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2212841Sgabeblack@google.com# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2312841Sgabeblack@google.com# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2412841Sgabeblack@google.com# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2512841Sgabeblack@google.com# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2612841Sgabeblack@google.com# 2712841Sgabeblack@google.com# Authors: Nathan Binkert 2812841Sgabeblack@google.com 2912841Sgabeblack@google.comfrom __future__ import print_function 3012841Sgabeblack@google.com 3112841Sgabeblack@google.com__all__ = [ 'multidict' ] 3212841Sgabeblack@google.com 3312841Sgabeblack@google.comclass multidict(object): 3412841Sgabeblack@google.com def __init__(self, parent = {}, **kwargs): 3512841Sgabeblack@google.com self.local = dict(**kwargs) 3612841Sgabeblack@google.com self.parent = parent 3712841Sgabeblack@google.com self.deleted = {} 3812841Sgabeblack@google.com 3912841Sgabeblack@google.com def __str__(self): 4012841Sgabeblack@google.com return str(dict(self.items())) 4112841Sgabeblack@google.com 4212841Sgabeblack@google.com def __repr__(self): 4312841Sgabeblack@google.com return repr(dict(list(self.items()))) 4412841Sgabeblack@google.com 4512841Sgabeblack@google.com def __contains__(self, key): 4612841Sgabeblack@google.com return key in self.local or key in self.parent 4712841Sgabeblack@google.com 4812841Sgabeblack@google.com def __delitem__(self, key): 4912841Sgabeblack@google.com try: 5012841Sgabeblack@google.com del self.local[key] 5112841Sgabeblack@google.com except KeyError as e: 5212841Sgabeblack@google.com if key in self.parent: 5312841Sgabeblack@google.com self.deleted[key] = True 5412841Sgabeblack@google.com else: 5512841Sgabeblack@google.com raise KeyError(e) 5612841Sgabeblack@google.com 5712841Sgabeblack@google.com def __setitem__(self, key, value): 5812841Sgabeblack@google.com self.deleted.pop(key, False) 5912841Sgabeblack@google.com self.local[key] = value 6012841Sgabeblack@google.com 6112841Sgabeblack@google.com def __getitem__(self, key): 6212841Sgabeblack@google.com try: 6312841Sgabeblack@google.com return self.local[key] 6412841Sgabeblack@google.com except KeyError as e: 6512841Sgabeblack@google.com if not self.deleted.get(key, False) and key in self.parent: 6612841Sgabeblack@google.com return self.parent[key] 6712841Sgabeblack@google.com else: 6812841Sgabeblack@google.com raise KeyError(e) 6912841Sgabeblack@google.com 7012841Sgabeblack@google.com def __len__(self): 7112841Sgabeblack@google.com return len(self.local) + len(self.parent) 7212841Sgabeblack@google.com 7312841Sgabeblack@google.com def next(self): 7412841Sgabeblack@google.com for key,value in self.local.items(): 7512841Sgabeblack@google.com 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 items(self): 86 for item in self.next(): 87 yield item 88 89 def keys(self): 90 for key,value in self.next(): 91 yield key 92 93 def values(self): 94 for key,value in self.next(): 95 yield value 96 97 def get(self, key, default=None): 98 try: 99 return self[key] 100 except KeyError as e: 101 return default 102 103 def setdefault(self, key, default): 104 try: 105 return self[key] 106 except KeyError: 107 self.deleted.pop(key, False) 108 self.local[key] = default 109 return default 110 111 def _dump(self): 112 print('multidict dump') 113 node = self 114 while isinstance(node, multidict): 115 print(' ', node.local) 116 node = node.parent 117 118 def _dumpkey(self, key): 119 values = [] 120 node = self 121 while isinstance(node, multidict): 122 if key in node.local: 123 values.append(node.local[key]) 124 node = node.parent 125 print(key, values) 126 127if __name__ == '__main__': 128 test1 = multidict() 129 test2 = multidict(test1) 130 test3 = multidict(test2) 131 test4 = multidict(test3) 132 133 test1['a'] = 'test1_a' 134 test1['b'] = 'test1_b' 135 test1['c'] = 'test1_c' 136 test1['d'] = 'test1_d' 137 test1['e'] = 'test1_e' 138 139 test2['a'] = 'test2_a' 140 del test2['b'] 141 test2['c'] = 'test2_c' 142 del test1['a'] 143 144 test2.setdefault('f', multidict) 145 146 print('test1>', list(test1.items())) 147 print('test2>', list(test2.items())) 148 #print(test1['a']) 149 print(test1['b']) 150 print(test1['c']) 151 print(test1['d']) 152 print(test1['e']) 153 154 print(test2['a']) 155 #print(test2['b']) 156 print(test2['c']) 157 print(test2['d']) 158 print(test2['e']) 159 160 for key in test2.keys(): 161 print(key) 162 163 test2.get('g', 'foo') 164 #test2.get('b') 165 test2.get('b', 'bar') 166 test2.setdefault('b', 'blah') 167 print(test1) 168 print(test2) 169 print(repr(test2)) 170 171 print(len(test2)) 172 173 test3['a'] = [ 0, 1, 2, 3 ] 174 175 print(test4) 176