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
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 |