git.fiddlerwoaroof.com
dupkeydict.py
a3fd722b
 # Copyright (c) 2011 Edward Langley
 # All rights reserved.
 # 
 # Redistribution and use in source and binary forms, with or without
 # modification, are permitted provided that the following conditions
 # are met:
 # 
 # Redistributions of source code must retain the above copyright notice,
 # this list of conditions and the following disclaimer.
 # 
 # Redistributions in binary form must reproduce the above copyright
 # notice, this list of conditions and the following disclaimer in the
 # documentation and/or other materials provided with the distribution.
 # 
 # Neither the name of the project's author nor the names of its
 # contributors may be used to endorse or promote products derived from
 # this software without specific prior written permission.
 # 
 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 # HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 # TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
2494b03a
 import collections
 
 class dkeydict(collections.Mapping):
 	def __init__(self, items=None):
 		#: caching only
 		self.dict = {}
 
 		items = items or []
 		self.list = items.items() if hasattr(items, 'items') else items
 	def __iter__(self): return iter(self.list)
 	def __len__(self): return len(self.list)
 
 	def __getitem__(self, key):
 		result = []
 
 		#: which item to get
 		count = 0
 		counter = 0
 
 		#: how many?
 		num = 1
 
 		#: which ones to get?
 		skip = 0
 		idx = 0
 
 		if isinstance(key, tuple) and 1 < len(key) < 5:
 			if len(key) == 2:
 				key, count = key
 			elif len(key) == 3:
 				key, count, num = key
 			else:
 				key, count, num, skip = key
 
 			capturing = False
 			for k,v in reversed(self.list):
 				if k == key:
 					if len(result) == num: break
 
 					if counter >= count: capturing = True
 					counter += 1
 
 					if idx != skip:
 						capturing = False
 						idx += 1
 					else:
 						capturing = True
 						idx = 0
 
 					if capturing: result.append(v)
 
 
 
 		elif isinstance(key, slice):
 			return self.list[slice]
 		else:
 			if key in self.dict: return self.dict[key]
 			else:
 				result = reversed([v for k,v in self.list if k == key]).next()
 				self.dict[key] = result
 
 		return result