import unittest


class IterableCompareTestCase(unittest.TestCase):

    def assertIterablesAlmostEqual(self, set1, set2, precision):

        if len( set1 ) != len( set2 ):
            self.fail( "Iterables do not have the same length" )
            
        for ( s1, s2 ) in zip( set1, set2 ):
            self.assertAlmostEqual( s1, s2, precision )
            
            
    def assertCoordinatesAlmostEqual(self, set1, set2, precision):
        
        if len( set1 ) != len( set2 ):
            self.fail( "Iterables do not have the same length" )
            
        for ( s1, s2 ) in zip( set1, set2 ):
            self.assertIterablesAlmostEqual(
                set1 = s1,
                set2 = s2,
                precision = precision
                )
            

class Fake(object):
    pass


class ListFake(list):
    pass


class FakeBlackboard(object):
    
    def __init__(self, return_for):
        
        self._return_for = return_for
        self.reset()
        
        
    def read_instances_of(self, object_type):
        
        return self._return_for.get( object_type, [] )
    
    
    def notify(self, event):
        
        self._notifications.append( event )
        
        
    def write(self, entry):
        
        self._writes.append( entry )
        
        
    def erase(self, entry):
        
        self._erases.append( entry )
        
        
    def reset(self):
        
        self._notifications = []
        self._writes = []
        self._erases = []
        
        
class Append(object):
    
    def __init__(self):
        
        self.reset()
        
        
    def __call__(self, *args, **kwargs):
        
        self._calls.append( ( args, kwargs ) )
        
        
    def reset(self):
        
        self._calls = []
        
        
class Return(object):
    
    def __init__(self, values):
        
        self._orig = values
        self.reset()
        
        
    def __call__(self, *args, **kwargs):
        
        self._calls.append( ( args, kwargs ) )
        return self._values.pop( 0 )
    
    def reset(self):
        
        self._calls = []
        self._values = list( self._orig )
        
        
class Raise(object):
    
    def __init__(self, exception, message):
        
        self._exception = exception,
        self._message = message
        self.reset()
        
        
    def __call__(self, *args, **kwargs):
        
        self._calls.append( ( args, kwargs ) )
        raise self._exception, self._message
        
        
    def reset(self):
        
        self._calls = []