Set Provider

cf. Specification Pattern (pdf).



def get_by_specification(items, spec):
    
return [x for x in items if spec.is_satisfied_by(x)]

class SetProvider(object):

    
def __init__(self, alist, *args):
        
self.items = alist
        
self.specs = list(args)

    
def __getitem__(self, index):
        
return self.get_set(index)

    
def get_set(self, index):
        
'''
        returns items satisfied by a given specification
        '''

        
return set( get_by_specification(self.items, self.specs[index]) )

    
def get_set_complement(self, index):
        
'''
        returns items not satisfied by a given specification
        '''

        
return set(self.items) - self[index]

    
def get_union(self):
        
'''
        returns items that satisfy any specification
        '''

        
s = set()
        
for t in self:
            
s.update( t )
        
return s

    
def get_intersection(self):
        
'''
        returns items that satisfy all specifications
        '''

        
s = set( self.items )
        
for t in self:
            
s.intersection_update( t )
        
return s
    
    
def get_complement(self):
        
'''
        returns items not satisfied by any specification
        '''

        
return set([x for x in self.items if x not in self.get_union()])

    
def get_strict_complement(self):
        
'''
        returns items not satisfied by all specifications
        '''

        
return set([x for x in self.items if x not in self.get_intersection()])

    
def get_symmetric_difference(self):
        
'''
        returns items that satisfy an odd number of specifications
        '''

        
s = set()
        
for t in self:
            
s.symmetric_difference_update( t )
        
return s