155 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			155 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Python
		
	
	
	
| import py
 | |
| Item = py.test.Item
 | |
| Collector = py.test.collect.Collector
 | |
| 
 | |
| import copy
 | |
| import time
 | |
| 
 | |
| import UserDict
 | |
| 
 | |
| 
 | |
| class Repository(object):
 | |
|     '''like a trie'''
 | |
|     nothing = object()
 | |
| 
 | |
|     def __init__(self):   
 | |
|         self.root = self.newnode()
 | |
| 
 | |
|     def newnode(self):
 | |
|         return [self.nothing, OrderedDictMemo()]
 | |
| 
 | |
|     def copy(self):
 | |
|         newrepos = Repository()
 | |
|         newrepos.root = copy.deepcopy(self.root)
 | |
|         return newrepos
 | |
| 
 | |
|     def add(self, key, value):
 | |
|         node = self.root
 | |
|         for k in key:
 | |
|             node = node[1].setdefault(k, self.newnode())
 | |
|         node[0] = value
 | |
|         
 | |
|     def find_tuple(self, key=[]):
 | |
|         node = self.root
 | |
|         for k in key:
 | |
|             node = node[1][k]
 | |
|         return node
 | |
| 
 | |
|     def find(self, key=[]):
 | |
|         return self.find_tuple(key)[0]
 | |
| 
 | |
|     def haskey(self, key):
 | |
|         try:
 | |
|             value = self.find(key)
 | |
|         except KeyError:
 | |
|             return False
 | |
|         return True
 | |
| 
 | |
|     def haskeyandvalue(self, key):
 | |
|         if self.haskey(key):
 | |
|             value = self.find(key)
 | |
|             return value is not self.nothing
 | |
|         return False
 | |
|                     
 | |
|     def find_children(self, key=[]):
 | |
|         if self.haskey(key):
 | |
|             node = self.find_tuple(key)
 | |
|             return [list(key) + [childname] for childname in node[1].keys()]
 | |
|         return []
 | |
| 
 | |
|     def keys(self, startkey=[]):
 | |
|         ret = []
 | |
|         for key in self.find_children(startkey):
 | |
|             ret.append(key)
 | |
|             ret.extend(self.keys(key))
 | |
|         return ret   
 | |
| 
 | |
|     def removestalekeys(self, key):
 | |
|         if self.find_children(key) == [] and not self.haskeyandvalue(key):
 | |
|             if len(key) > 0:
 | |
|                 parent = self.find_tuple(key[:-1])
 | |
|                 del parent[1][key[-1]]
 | |
|                 self.removestalekeys(key[:-1])
 | |
| 
 | |
| 
 | |
|     def delete(self, key):
 | |
|         if self.haskeyandvalue(key):
 | |
|             node = self.find_tuple(key)
 | |
|             node[0] = self.newnode()[0]
 | |
|             self.removestalekeys(key)
 | |
| 
 | |
|     def delete_all(self, key):
 | |
|         if self.haskeyandvalue(key):
 | |
|             node = self.find_tuple(key)
 | |
|             node[0], node[1] = self.newnode()[0], self.newnode()[1]
 | |
|             self.removestalekeys(key)
 | |
|         
 | |
|     def values(self, startkey=[]):
 | |
|         return [self.find(key) for key in self.keys(startkey)]
 | |
| 
 | |
|     def items(self, startkey=[]):
 | |
|         return [(key, self.find(key)) for key in self.keys(startkey)]
 | |
| 
 | |
| 
 | |
| class OrderedDict(UserDict.DictMixin): 
 | |
|     '''like a normal dict, but keys are ordered by time of setting'''
 | |
|     def __init__(self, *args, **kwargs):
 | |
|         self._dict = dict(*args, **kwargs)
 | |
|         self._keys = self._dict.keys()
 | |
| 
 | |
|     def __getitem__(self, key):
 | |
|         return self._dict.__getitem__(key)
 | |
| 
 | |
|     def __setitem__(self, key, value):
 | |
|         self._dict.__setitem__(key, value)
 | |
|         try:
 | |
|             self._keys.remove(key)
 | |
|         except ValueError:
 | |
|             pass
 | |
|         self._keys.append(key)
 | |
|         
 | |
|     def __delitem__(self, key):
 | |
|         self._dict.__delitem__(key)
 | |
|         self._keys.remove(key)
 | |
| 
 | |
|     def keys(self):
 | |
|         return self._keys[:]
 | |
| 
 | |
|     def copy(self):
 | |
|         new = OrderedDict()
 | |
|         for key, value in self.iteritems():
 | |
|             new[key] = value
 | |
|         return new
 | |
| 
 | |
| class OrderedDictMemo(UserDict.DictMixin):
 | |
|     '''memorize all keys and how they were ordered'''
 | |
|     def __init__(self, *args, **kwargs):
 | |
|         self._dict = dict(*args, **kwargs)
 | |
|         self._keys = self._dict.keys()
 | |
| 
 | |
|     def __getitem__(self, key):
 | |
|         return self._dict.__getitem__(key)
 | |
| 
 | |
|     def __setitem__(self, key, value):
 | |
|         self._dict.__setitem__(key, value)
 | |
|         if key not in self._keys:
 | |
|             self._keys.append(key)
 | |
|         
 | |
|     def __delitem__(self, key):
 | |
|         self._dict.__delitem__(key)
 | |
|         
 | |
|     def keys(self):
 | |
|         return [key for key in self._keys if key in self._dict]
 | |
| 
 | |
|     def copy(self):
 | |
|         new = OrderedDict()
 | |
|         for key, value in self.iteritems():
 | |
|             new[key] = value
 | |
|         return new
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 |