Beispiel #1
0
    def test_tracebacks(self):
        'Tracebacks have correct file names and line numbers'

        # If we want tracebacks to make sense, then the reported file names and
        # line numbers need to associate with the code being executed
        # regardless which block represents and executes the code.

        def test(tb, lineno, filename):
            self.assertEqual(tb.tb_lineno, lineno+1)
            self.assertEqual(tb.tb_frame.f_code.co_filename, filename)

        def tracebacks():
            "A list of the current exception's traceback objects."
            tb = sys.exc_info()[2]
            l = [tb]
            while tb.tb_next is not None:
                tb = tb.tb_next
                l.append(tb)
            return l

        class File(StringIO, object):
            "Extend StringIO with a 'name' attribute."
            def __init__(self, name, *args, **kw):
                super(File, self).__init__(*args, **kw)
                self.name = name

        a = Block(File('foo/a.py', 'y = x'))
        try:
            a.execute({})
        except NameError, e:
            test(tracebacks()[-1], 1, 'foo/a.py')
Beispiel #2
0
def test_basic_02():
    """Another test of the basic use of a Block."""
    code = 'y = x + 1'
    b = Block(code)
    assert_equal(b.inputs, set(['x']))
    assert_equal(b.outputs, set(['y']))

    names = dict(x=100)
    b.execute(names)
    assert_equal(sorted(names), ['x', 'y'])
    assert_equal(names['x'], 100)
    assert_equal(names['y'], 101)
Beispiel #3
0
def test_basic_01():
    """Test basic use of a Block."""
    code = 'x = 100\ny = x + 1'
    b = Block(code)
    assert_equal(b.inputs, set([]))
    assert_equal(b.outputs, set(['x','y']))

    names = dict()
    b.execute(names)
    assert_equal(sorted(names), ['x', 'y'])
    assert_equal(names['x'], 100)
    assert_equal(names['y'], 101)
Beispiel #4
0
def test_basic_02():
    """Another test of the basic use of a Block."""
    code = 'y = x + 1'
    b = Block(code)
    assert_equal(b.inputs, set(['x']))
    assert_equal(b.outputs, set(['y']))

    names = dict(x=100)
    b.execute(names)
    assert_equal(sorted(names), ['x', 'y'])
    assert_equal(names['x'], 100)
    assert_equal(names['y'], 101)
Beispiel #5
0
def test_basic_01():
    """Test basic use of a Block."""
    code = 'x = 100\ny = x + 1'
    b = Block(code)
    assert_equal(b.inputs, set([]))
    assert_equal(b.outputs, set(['x', 'y']))
    assert_equal(b.const_assign, (set(['x']), ['x = 100']))

    names = dict()
    b.execute(names)
    assert_equal(sorted(names), ['x', 'y'])
    assert_equal(names['x'], 100)
    assert_equal(names['y'], 101)
Beispiel #6
0
 def test_optimization_no_filenames_in_tracebacks(self):
     'Optimization: No filenames in tracebacks'
     b = Block('import operator\n'
               'x,d = 2,{}\n'
               'for i in range(10):\n'
               '  d[i] = repr(i)\n'
               '  x *= 2\n'
               'sum = lambda l, add=operator.add: reduce(add, l)\n'
               'd = (sum(d.keys()), sum(d.values()))\n',
               no_filenames_in_tracebacks = True)
     c = {}
     b.execute(c)
     assert c['x'] == 2**11
     assert c['d'] == (9*10/2, '0123456789')
Beispiel #7
0
    def test_caching_code(self):
        "Caching: '_code'"

        b,c = Block('a=2'), {}
        b._code
        b.ast = Block('a=3').ast
        b.execute(c)
        self.assertEqual(c['a'], 3)

        b,c = Block('a=2'), {}
        b._code
        b.sub_blocks = [Block('a=3')]
        b.execute(c)
        self.assertEqual(c['a'], 3)

        b,c = Block('a=3; a=2'), {}
        b._code
        b.sub_blocks.pop()
        b.execute(c)
        self.assertEqual(c['a'], 3)

        b,c = Block(''), {}
        b._code
        b.sub_blocks.append(Block('a=3'))
        b.sub_blocks = [Block('a=3')]
        b.execute(c)
        assert 'a' in c
    def test_caching_code(self):
        "Caching: '_code'"

        b, c = Block('a=2'), {}
        b._code
        b.ast = Block('a=3').ast
        b.execute(c)
        self.assertEqual(c['a'], 3)

        b, c = Block('a=2'), {}
        b._code
        b.sub_blocks = [Block('a=3')]
        b.execute(c)
        self.assertEqual(c['a'], 3)

        b, c = Block('a=3; a=2'), {}
        b._code
        b.sub_blocks.pop()
        b.execute(c)
        self.assertEqual(c['a'], 3)

        b, c = Block(''), {}
        b._code
        b.sub_blocks.append(Block('a=3'))
        b.sub_blocks = [Block('a=3')]
        b.execute(c)
        assert 'a' in c
Beispiel #9
0
    def test3(self):
        """ Same sized array assignments within 'with' block
        """

        file_object = open(os.path.join(self.code_dir, 'test3.py'), 'r')
        code = file_object.read()
        file_object.close()

        b = Block(code)
        b.execute(self.context)

        desired_vp = arange(0., 10., 1.)
        desired_vs = arange(0., 100., 10.)

        # Check equal
        self.assertTrue((desired_vp == self.context['vp']).all())
        self.assertTrue((desired_vs == self.context['vs']).all())
Beispiel #10
0
    def test3(self):
        """ Same sized array assignments within 'with' block
        """

        file_object = open(os.path.join(self.code_dir,'test3.py'), 'r')
        code = file_object.read()
        file_object.close()

        b = Block(code)
        b.execute(self.context)

        desired_vp = arange(0., 10., 1.)
        desired_vs = arange(0., 100., 10.)

        # Check equal
        self.assertTrue((desired_vp == self.context['vp']).all())
        self.assertTrue((desired_vs == self.context['vs']).all())
Beispiel #11
0
    def test2(self):
        """ Different sized arrays
        """

        file_object = open(os.path.join(self.code_dir, 'test2.py'), 'r')
        code = file_object.read()
        file_object.close()

        b = Block(code)
        b.execute(self.context)

        depth = arange(0., 10000., 1000.)
        desired_vp = zeros(depth.shape)
        desired_vs = zeros(depth.shape)
        desired_vp[(depth < 4000.0) & (depth > 1000.0)] = 1.0
        desired_vs[(depth < 4000.0) & (depth > 1000.0)] = 1.5

        # Check equal
        self.assertTrue((desired_vp == self.context['vp']).all())
        self.assertTrue((desired_vs == self.context['vs']).all())
Beispiel #12
0
    def test2(self):
        """ Different sized arrays
        """

        file_object = open(os.path.join(self.code_dir,'test2.py'), 'r')
        code = file_object.read()
        file_object.close()

        b = Block(code)
        b.execute(self.context)

        depth = arange(0., 10000., 1000.)
        desired_vp = zeros(depth.shape)
        desired_vs = zeros(depth.shape)
        desired_vp[(depth<4000.0) & (depth > 1000.0)] = 1.0
        desired_vs[(depth<4000.0) & (depth > 1000.0)] = 1.5

        # Check equal
        self.assertTrue((desired_vp == self.context['vp']).all())
        self.assertTrue((desired_vs == self.context['vs']).all())
Beispiel #13
0
    def test_block_events(self):
        import numpy
        from codetools.blocks.api import Block

        context = DataContext(name="data")
        context.on_trait_change(self.event_listener, 'items_modified')
        context.defer_events = True
        context['a'] = 4
        context['b'] = numpy.array((1,2,3))
        context.defer_events = False

        self.assertEqual(self.event_count, 1)

        multi_context = MultiContext(context, name="multi")
        multi_context.on_trait_change(self.event_listener, 'items_modified')

        block = Block("c = a * b")
        block.execute(multi_context)

        # we expect one event from data context, one from multi context
        self.assertEqual(self.event_count, 3)
Beispiel #14
0
    def test_block_events(self):
        import numpy
        from codetools.blocks.api import Block

        context = DataContext(name="data")
        context.on_trait_change(self.event_listener, 'items_modified')
        context.defer_events = True
        context['a'] = 4
        context['b'] = numpy.array((1, 2, 3))
        context.defer_events = False

        self.assertEqual(self.event_count, 1)

        multi_context = MultiContext(context, name="multi")
        multi_context.on_trait_change(self.event_listener, 'items_modified')

        block = Block("c = a * b")
        block.execute(multi_context)

        # we expect one event from data context, one from multi context
        self.assertEqual(self.event_count, 3)
class ParametricInteractorTestCase(unittest.TestCase):
    """ Unit testing for ParametricInteractor
    """

    def setUp(self):
        code = "from blockcanvas.debug.my_operator import add, mul\n" \
               "c = add(a,b)\n" \
               "d = mul(c, 2)\n" \
               "e = mul(c, 3)\n" \
               "f = add(d,e)"

        self.block=Block(code)

        # Context setup.
        self.context = MultiContext(DataContext(name='Data'),{})
        self.context['a'] = 1
        self.context['b'] = 2


    def test_attributes(self):
        """ Test if creation of attributes is working correctly
        """
        interactor = ParametricInteractor(context=self.context,block=self.block)

        self.assertTrue(hasattr(interactor, interactor._input_prefix + "a"))
        self.assertTrue(hasattr(interactor, interactor._input_prefix + "b"))

        # Check if the parameter items were written correctly
        attribute_a = getattr(interactor, interactor._input_prefix+'a')
        attribute_b = getattr(interactor, interactor._input_prefix+'b')

        self.assertEqual(attribute_a.step, 0)
        self.assertEqual(attribute_a.low, 1)
        self.assertEqual(attribute_a.high, 1)

        self.assertEqual(attribute_b.step, 0)
        self.assertEqual(attribute_b.low, 2)
        self.assertEqual(attribute_b.high, 2)

        # Check if the inputs in the interactor are right
        self.assertEqual(interactor.inputs, list(self.block.inputs))


    def test_create_shadows(self):
        """ Test if creating shadows is working correctly
        """
        interactor = ParametricInteractor(context=self.context,block=self.block)

        # Change the parameters for the attributes
        attribute_a = getattr(interactor, interactor._input_prefix+'a')
        attribute_b = getattr(interactor, interactor._input_prefix+'b')

        attribute_a.high = 4
        attribute_a.step = 1

        attribute_b.high = 3
        attribute_b.step = 1

        # Create the shadows.
        interactor._update_contexts_button_changed()

        # Check if the shadows were created correctly.
        self.assertEqual(len(self.context.shadows),
                len(attribute_a.output_list)*len(attribute_b.output_list))

        # Check if the shadow context gives desired result.
        self.block.execute(self.context.shadows[-1])
        self.assertEqual(self.context.shadows[-1]['f'],
               5*(self.context.shadows[-1]['a']+self.context.shadows[-1]['b']))
class ConfigurableInteractorTestCase(unittest.TestCase):
    """ Unit testing for ConfigurableInteractor
    """

    def setUp(self):
        code = "from blockcanvas.debug.my_operator import add,mul\n"\
               "c = add(a, b)\n" \
               "d = mul(c, 2)\n" \
               "e = mul(c, 3)\n" \
               "f = add(d, e)\n" \
               "g = add(f, 3)\n" \
               "h = mul(g, f)\n" \
               "i = mul(g,h)"

        self.block=Block(code)

        # Context setup.
        self.context = MultiContext(DataContext(name='Data'),{})
        self.context['a'] = 1.0
        self.context['b'] = 2

        self.block.execute(self.context)

        # ConfigurableInteractor setup
        i_config = InteractorConfig(var_configs=[VariableConfig(name='a',
                                                         type='Shadow'),
                                                 VariableConfig(name='b',
                                                         type='Parametric'),
                                                 VariableConfig(name='c',
                                                         type='Shadow'),
                                                 VariableConfig(name='d',
                                                         type='Parametric'),
                                                 VariableConfig(name='e',
                                                   type='Stochastic: Constant'),
                                                 VariableConfig(name='f',
                                                   type='Stochastic: Gaussian'),
                                                 VariableConfig(name='g',
                                                 type='Stochastic: Triangular'),
                                                 VariableConfig(name='h',
                                                    type='Stochastic: Uniform'),
                                                 ])
        self.interactor = ConfigurableInteractor(interactor_config=i_config,
                                                 block=self.block,
                                                 context=self.context)

        # Temp dir
        self.temp_dir = tempfile.gettempdir()


    def test_build_vars(self):
        """ Does the interactor create the right traits for the types of
            of interactors
        """

        self.failUnless(isinstance(self.interactor.interactor_shadow,
                                   ShadowInteractor))
        self.failUnless(isinstance(self.interactor.interactor_parametric,
                                   ParametricInteractor))
        self.failUnless(isinstance(
           self.interactor.interactor_stochastic_constant,StochasticInteractor))
        self.failUnless(isinstance(
           self.interactor.interactor_stochastic_gaussian,StochasticInteractor))
        self.failUnless(isinstance(
           self.interactor.interactor_stochastic_triangular,
           StochasticInteractor))
        self.failUnless(isinstance(
           self.interactor.interactor_stochastic_uniform, StochasticInteractor))


    def test_load_project_ranges_for_shadow_interactor(self):
        """ Does loading ranges from file work for shadow interactor ?
        """

        child_int = self.interactor.interactor_shadow
        file_path = os.path.join(os.path.dirname(__file__), 'data',
                                 'project_ranges.txt')

        # Applying the ranges to the shadow interactor in the configurable
        # interactor
        self.interactor.load_ranges_from_files({'shadow':file_path})
        child_int._view_items()

        self.assertEqual(len(child_int.ranges.keys()), 42)
        self.assertAlmostEqual(child_int.input_a__high, 5)
        self.assertAlmostEqual(child_int.input_a__low, 3.4)
        self.assertEqual(child_int.input_a, self.context['a'])


    def test_save_project_ranges_for_shadow_interactor(self):
        """ Does saving ranges to file work for shadow interactor ?
        """

        child_int = self.interactor.interactor_shadow
        f_path = os.path.join(self.temp_dir,'test_save_ranges_for_shadow.txt')

        child_int._view_items()
        child_int.input_a__high = 5.0
        self.interactor.save_ranges_to_files({'shadow': f_path})

        # Read the saved file
        file_object = open(f_path, 'r')
        line = file_object.read()
        line = [name.strip() for name in line.split()]
        file_object.close()
        os.remove(f_path)

        # Check results
        self.assertEqual(len(line), 6)
        self.assertEqual(line[2], str(5.0))


    def test_load_project_ranges_for_parametric_interactor(self):
        """ Does loading ranges from file work for parametric interactor ?
        """

        child_int = self.interactor.interactor_parametric
        file_path = os.path.join(os.path.dirname(__file__), 'data',
                                 'project_ranges.txt')

        self.interactor.load_ranges_from_files({'parametric': file_path})
        child_int._view_items()

        self.assertEqual(len(child_int.ranges.keys()), 42)
        self.assertAlmostEqual(child_int.input_b.low, 1.0)
        self.assertAlmostEqual(child_int.input_b.high, 6.0)
        self.assertEqual(child_int.input_b.step, 0.0)
        self.assertEqual(child_int.input_b.input_value, self.context['b'])


    def test_save_project_ranges_for_parametric_interactor(self):
        """ Does saving ranges to file work for parametric interactor ?
        """

        file_path = os.path.join(self.temp_dir,
                                 'test_save_ranges_for_parametric.txt')

        child_int = self.interactor.interactor_parametric
        child_int._view_items()

        child_int.input_b.low = 2
        child_int.input_b.high = 3
        child_int.input_b.step = 0.5
        self.interactor.save_ranges_to_files({'parametric':file_path})

        # Read the saved file
        file_object = open(file_path, 'r')
        lines = file_object.readlines()
        lines = [line.split() for line in lines]
        file_object.close()
        os.remove(file_path)

        self.assertEqual(len(lines), 2)
        self.assertEqual(len(lines[0]), 4)
        self.assertEqual(len(lines[1]), 4)
        self.assertEqual(lines[0][1], str(2))
        self.assertEqual(lines[0][2], str(3))
        self.assertEqual(lines[0][3], str(0))


    def test_load_project_ranges_for_stochastic_constant_interactor(self):
        """ Does loading parameters from file work for stochastic interactor
            with constant distribution ?
        """

        child_int = self.interactor.interactor_stochastic_constant
        file_path = os.path.join(os.path.dirname(__file__), 'data',
                                 'stochastic_constant_ranges.txt')

        self.interactor.load_ranges_from_files({'stochastic_constant':
                                                file_path})
        child_int._view_items()
        self.assertEqual(child_int.input_e.distribution.value, 45)


    def test_save_project_ranges_for_stochastic_constant_interactor(self):
        """ Does saving parameters to file work for stochastic interactor with
            constant distribution ?
        """

        file_path = os.path.join(self.temp_dir,
                                 'test_save_ranges_for_stoch_constant.txt')

        child_int = self.interactor.interactor_stochastic_constant
        child_int._view_items()

        child_int.input_e.distribution.value = 37.5
        self.interactor.save_ranges_to_files({'stochastic_constant': file_path})

        # Read the saved file
        file_object = open(file_path, 'r')
        lines = file_object.readlines()
        lines = [line.split() for line in lines]
        file_object.close()
        os.remove(file_path)

        self.assertEqual(len(lines), 1)
        self.assertEqual(len(lines[0]), 2)
        self.assertEqual(lines[0][1], str(37.5))


    def test_load_project_ranges_for_stochastic_gaussian_interactor(self):
        """ Does loading parameters from file work for stochastic interactor
            with gaussian distribution ?
        """

        child_int = self.interactor.interactor_stochastic_gaussian
        file_path = os.path.join(os.path.dirname(__file__), 'data',
                                 'stochastic_gaussian_ranges.txt')
        self.interactor.load_ranges_from_files({'stochastic_gaussian':
                                                file_path})
        child_int._view_items()
        self.assertEqual(child_int.input_f.distribution.mean, 39)
        self.assertEqual(child_int.input_f.distribution.std, 3)


    def test_save_project_ranges_for_stochastic_gaussian_interactor(self):
        """ Does saving parameters to file work for stochastic interactor
            with gaussian distribution ?
        """

        file_path = os.path.join(self.temp_dir,
                                 'test_save_ranges_for_stoch_gaussian.txt')
        child_int = self.interactor.interactor_stochastic_gaussian
        child_int._view_items()

        child_int.input_f.distribution.mean = 200
        child_int.input_f.distribution.std = 0.5
        self.interactor.save_ranges_to_files({'stochastic_gaussian': file_path})

        # Read the saved file
        file_object = open(file_path, 'r')
        lines = file_object.readlines()
        lines = [line.split() for line in lines]
        file_object.close()
        os.remove(file_path)

        self.assertEqual(len(lines), 1)
        self.assertEqual(len(lines[0]), 3)
        self.assertEqual(lines[0][1], str(200.0))
        self.assertEqual(lines[0][2], str(0.5))


    def test_load_project_ranges_for_stochastic_triangular_interactor(self):
        """ Does loading parameters from file work for triangular interactor
            with triangular distribution ?
        """

        child_int = self.interactor.interactor_stochastic_triangular
        file_path = os.path.join(os.path.dirname(__file__), 'data',
                                 'stochastic_triangular_ranges.txt')
        self.interactor.load_ranges_from_files({'stochastic_triangular':
                                                file_path})
        child_int._view_items()
        self.assertEqual(child_int.input_g.distribution.mode, 44)
        self.assertEqual(child_int.input_g.distribution.low, 39)
        self.assertEqual(child_int.input_g.distribution.high, 49)


    def test_save_project_ranges_for_stochastic_triangular_interactor(self):
        """ Does saving parameters to file work for stochastic interactor
            with triangular distribution ?
        """

        file_path = os.path.join(self.temp_dir,
                                 'test_save_ranges_for_stoch_triangular.txt')
        child_int = self.interactor.interactor_stochastic_triangular
        child_int._view_items()

        child_int.input_g.distribution.mode = 40.0
        child_int.input_g.distribution.low = 30.0
        child_int.input_g.distribution.high = 50.0
        self.interactor.save_ranges_to_files({'stochastic_triangular':
                                              file_path})

        # Read the saved file
        file_object = open(file_path, 'r')
        lines = file_object.readlines()
        lines = [line.split() for line in lines]
        file_object.close()
        os.remove(file_path)

        self.assertEqual(len(lines), 1)
        self.assertEqual(len(lines[0]), 4)
        self.assertEqual(lines[0][1], str(40.0))
        self.assertEqual(lines[0][2], str(30.0))
        self.assertEqual(lines[0][3], str(50.0))


    def test_load_project_ranges_for_stochastic_uniform_interactor(self):
        """ Does loading parameters from file work for stochastic interactor
            with uniform distribution ?
        """

        child_int = self.interactor.interactor_stochastic_uniform
        file_path = os.path.join(os.path.dirname(__file__), 'data',
                                 'stochastic_uniform_ranges.txt')
        self.interactor.load_ranges_from_files({'stochastic_uniform':file_path})
        child_int._view_items()
        self.assertEqual(child_int.input_h.distribution.low, 40)
        self.assertEqual(child_int.input_h.distribution.high, 58)


    def test_save_project_ranges_for_stochastic_uniform_interactor(self):
        """ Does saving parameters to file work for stochastic interactor
            with uniform distribution ?
        """

        file_path = os.path.join(self.temp_dir,
                                 'test_save_ranges_for_stoch_uniform.txt')
        child_int = self.interactor.interactor_stochastic_uniform
        child_int._view_items()

        child_int.input_h.distribution.low = 30.0
        child_int.input_h.distribution.high = 50.0
        self.interactor.save_ranges_to_files({'stochastic_uniform': file_path})

        # Read the saved file
        file_object = open(file_path, 'r')
        lines = file_object.readlines()
        lines = [line.split() for line in lines]
        file_object.close()
        os.remove(file_path)

        self.assertEqual(len(lines), 1)
        self.assertEqual(len(lines[0]), 3)
        self.assertEqual(lines[0][1], str(30.0))
        self.assertEqual(lines[0][2], str(50.0))


    def test_load_global_ranges_with_project_ranges(self):
        """ Do global ranges get overwritten by the project settings ?
        """

        code = "from blockcanvas.debug.my_operator import add,mul\n"\
               "d = mul(a, b)\n" \
               "e = mul(c, 3)\n" \
               "f = add(d,e)"
        self.block = Block(code)
        self.context['c'] = 2.0

        # This is to be done because the interactor doesn't get updated with
        # change in block.
        i_config = InteractorConfig(var_configs=[VariableConfig(name='a',
                                                 type='Shadow'),
                                         VariableConfig(name='b',
                                                 type='Parametric'),
                                         VariableConfig(name='c',
                                                 type='Shadow'),
                                         VariableConfig(name='d',
                                                 type='Parametric')])
        self.interactor = ConfigurableInteractor(block=self.block,
                                                 context=self.context,
                                                 interactor_config=i_config)

        child_int = self.interactor.interactor_shadow
        global_file_path = os.path.join(os.path.dirname(__file__), 'data',
                                        'global_user_range.txt')
        project_file_path = os.path.join(os.path.dirname(__file__), 'data',
                                         'project_ranges.txt')

        self.interactor.load_ranges_from_files({'shadow':project_file_path},
                                               {'shadow':global_file_path})
        child_int._view_items()

        # Range of a is obtained from the project settings and not the
        # global preferences
        self.assertAlmostEqual(child_int.input_a__low, 3.4)
        self.assertAlmostEqual(child_int.input_a__high, 5.0)

        self.assertNotEqual(child_int.input_a__low, 0.15)
        self.assertNotEqual(child_int.input_a__high, 9.3)

        # Range of c is obtained from the global preferences
        self.assertAlmostEqual(child_int.input_c__low, 2.0)
        self.assertAlmostEqual(child_int.input_c__high, 7.0)


    def test_load_global_ranges_without_project_ranges(self):
        """ Do global ranges get used when there are no project settings ?
        """

        code = "from blockcanvas.debug.my_operator import add,mul\n"\
               "d = mul(a, b)\n" \
               "e = mul(c, 3)\n" \
               "f = add(d,e)"
        self.block = Block(code)
        self.context['c'] = 2.0

        # This is to be done because the interactor doesn't get updated with
        # change in block.
        i_config = InteractorConfig(var_configs=[VariableConfig(name='a',
                                                         type='Shadow'),
                                                 VariableConfig(name='b',
                                                         type='Parametric'),
                                                 VariableConfig(name='c',
                                                         type='Shadow'),
                                                 VariableConfig(name='d',
                                                         type='Parametric')])
        self.interactor = ConfigurableInteractor(block=self.block,
                                                 context=self.context,
                                                 interactor_config=i_config)

        child_int = self.interactor.interactor_shadow
        global_file_path = os.path.join(os.path.dirname(__file__), 'data',
                                        'global_user_range.txt')

        self.interactor.load_ranges_from_files({}, {'shadow':global_file_path})
        child_int._view_items()

        # Range of a is obtained from the project settings and not the
        # global preferences
        self.assertAlmostEqual(child_int.input_a__low, 0.15)
        self.assertAlmostEqual(child_int.input_a__high, 9.3)

        # Range of c is obtained from the global preferences
        self.assertAlmostEqual(child_int.input_c__low, 2.0)
        self.assertAlmostEqual(child_int.input_c__high, 7.0)
Beispiel #17
0
           'from numpy import zeros\n'\
           'from codetools.contexts.with_mask import Mask\n'\
           'with Mask((depth < 4000.0) & (depth > 1000.0)):vp=1.5 ; vs=1.0'

    ##     # Expanded form of with statement taken from PEP 343. This is just for testing
    ##     code =   'from numpy import zeros\n'\
    ##              'array_len = depth.shape\n'\
    ##              'vp = zeros(array_len)\n'\
    ##              'vs = zeros(array_len)\n'\
    ##              'from codetools.contexts.with_mask import Mask\n'\
    ##              'mgr = Mask((depth < 4000.0) & (depth > 1000.0))\n'\
    ##              'exit_code = mgr.__exit__\n'\
    ##              'mgr.__enter__()\n'\
    ##              'exc = True\n'\
    ##              'try:\n'\
    ##              '    try:\n'\
    ##              '        vp = 1.0\n'\
    ##              '        vs = 1.5\n'\
    ##              '    except:\n'\
    ##              '        exc = False\n'\
    ##              'finally:\n'\
    ##              '    if exc:\n'\
    ##              '        exit_code(None, None, None)'

    b = Block(code)
    b.execute(context)
    print('vp', context['vp'])
    print('vs', context['vs'])

### EOF ------------------------------------------------------------------------
class ConfigurableInteractorTestCase(unittest.TestCase):
    """ Unit testing for ConfigurableInteractor
    """
    def setUp(self):
        code = "from blockcanvas.debug.my_operator import add,mul\n"\
               "c = add(a, b)\n" \
               "d = mul(c, 2)\n" \
               "e = mul(c, 3)\n" \
               "f = add(d, e)\n" \
               "g = add(f, 3)\n" \
               "h = mul(g, f)\n" \
               "i = mul(g,h)"

        self.block = Block(code)

        # Context setup.
        self.context = MultiContext(DataContext(name='Data'), {})
        self.context['a'] = 1.0
        self.context['b'] = 2

        self.block.execute(self.context)

        # ConfigurableInteractor setup
        i_config = InteractorConfig(var_configs=[
            VariableConfig(name='a', type='Shadow'),
            VariableConfig(name='b', type='Parametric'),
            VariableConfig(name='c', type='Shadow'),
            VariableConfig(name='d', type='Parametric'),
            VariableConfig(name='e', type='Stochastic: Constant'),
            VariableConfig(name='f', type='Stochastic: Gaussian'),
            VariableConfig(name='g', type='Stochastic: Triangular'),
            VariableConfig(name='h', type='Stochastic: Uniform'),
        ])
        self.interactor = ConfigurableInteractor(interactor_config=i_config,
                                                 block=self.block,
                                                 context=self.context)

        # Temp dir
        self.temp_dir = tempfile.gettempdir()

    def test_build_vars(self):
        """ Does the interactor create the right traits for the types of
            of interactors
        """

        self.failUnless(
            isinstance(self.interactor.interactor_shadow, ShadowInteractor))
        self.failUnless(
            isinstance(self.interactor.interactor_parametric,
                       ParametricInteractor))
        self.failUnless(
            isinstance(self.interactor.interactor_stochastic_constant,
                       StochasticInteractor))
        self.failUnless(
            isinstance(self.interactor.interactor_stochastic_gaussian,
                       StochasticInteractor))
        self.failUnless(
            isinstance(self.interactor.interactor_stochastic_triangular,
                       StochasticInteractor))
        self.failUnless(
            isinstance(self.interactor.interactor_stochastic_uniform,
                       StochasticInteractor))

    def test_load_project_ranges_for_shadow_interactor(self):
        """ Does loading ranges from file work for shadow interactor ?
        """

        child_int = self.interactor.interactor_shadow
        file_path = os.path.join(os.path.dirname(__file__), 'data',
                                 'project_ranges.txt')

        # Applying the ranges to the shadow interactor in the configurable
        # interactor
        self.interactor.load_ranges_from_files({'shadow': file_path})
        child_int._view_items()

        self.assertEqual(len(child_int.ranges.keys()), 42)
        self.assertAlmostEqual(child_int.input_a__high, 5)
        self.assertAlmostEqual(child_int.input_a__low, 3.4)
        self.assertEqual(child_int.input_a, self.context['a'])

    def test_save_project_ranges_for_shadow_interactor(self):
        """ Does saving ranges to file work for shadow interactor ?
        """

        child_int = self.interactor.interactor_shadow
        f_path = os.path.join(self.temp_dir, 'test_save_ranges_for_shadow.txt')

        child_int._view_items()
        child_int.input_a__high = 5.0
        self.interactor.save_ranges_to_files({'shadow': f_path})

        # Read the saved file
        file_object = open(f_path, 'r')
        line = file_object.read()
        line = [name.strip() for name in line.split()]
        file_object.close()
        os.remove(f_path)

        # Check results
        self.assertEqual(len(line), 6)
        self.assertEqual(line[2], str(5.0))

    def test_load_project_ranges_for_parametric_interactor(self):
        """ Does loading ranges from file work for parametric interactor ?
        """

        child_int = self.interactor.interactor_parametric
        file_path = os.path.join(os.path.dirname(__file__), 'data',
                                 'project_ranges.txt')

        self.interactor.load_ranges_from_files({'parametric': file_path})
        child_int._view_items()

        self.assertEqual(len(child_int.ranges.keys()), 42)
        self.assertAlmostEqual(child_int.input_b.low, 1.0)
        self.assertAlmostEqual(child_int.input_b.high, 6.0)
        self.assertEqual(child_int.input_b.step, 0.0)
        self.assertEqual(child_int.input_b.input_value, self.context['b'])

    def test_save_project_ranges_for_parametric_interactor(self):
        """ Does saving ranges to file work for parametric interactor ?
        """

        file_path = os.path.join(self.temp_dir,
                                 'test_save_ranges_for_parametric.txt')

        child_int = self.interactor.interactor_parametric
        child_int._view_items()

        child_int.input_b.low = 2
        child_int.input_b.high = 3
        child_int.input_b.step = 0.5
        self.interactor.save_ranges_to_files({'parametric': file_path})

        # Read the saved file
        file_object = open(file_path, 'r')
        lines = file_object.readlines()
        lines = [line.split() for line in lines]
        file_object.close()
        os.remove(file_path)

        self.assertEqual(len(lines), 2)
        self.assertEqual(len(lines[0]), 4)
        self.assertEqual(len(lines[1]), 4)
        self.assertEqual(lines[0][1], str(2))
        self.assertEqual(lines[0][2], str(3))
        self.assertEqual(lines[0][3], str(0))

    def test_load_project_ranges_for_stochastic_constant_interactor(self):
        """ Does loading parameters from file work for stochastic interactor
            with constant distribution ?
        """

        child_int = self.interactor.interactor_stochastic_constant
        file_path = os.path.join(os.path.dirname(__file__), 'data',
                                 'stochastic_constant_ranges.txt')

        self.interactor.load_ranges_from_files(
            {'stochastic_constant': file_path})
        child_int._view_items()
        self.assertEqual(child_int.input_e.distribution.value, 45)

    def test_save_project_ranges_for_stochastic_constant_interactor(self):
        """ Does saving parameters to file work for stochastic interactor with
            constant distribution ?
        """

        file_path = os.path.join(self.temp_dir,
                                 'test_save_ranges_for_stoch_constant.txt')

        child_int = self.interactor.interactor_stochastic_constant
        child_int._view_items()

        child_int.input_e.distribution.value = 37.5
        self.interactor.save_ranges_to_files(
            {'stochastic_constant': file_path})

        # Read the saved file
        file_object = open(file_path, 'r')
        lines = file_object.readlines()
        lines = [line.split() for line in lines]
        file_object.close()
        os.remove(file_path)

        self.assertEqual(len(lines), 1)
        self.assertEqual(len(lines[0]), 2)
        self.assertEqual(lines[0][1], str(37.5))

    def test_load_project_ranges_for_stochastic_gaussian_interactor(self):
        """ Does loading parameters from file work for stochastic interactor
            with gaussian distribution ?
        """

        child_int = self.interactor.interactor_stochastic_gaussian
        file_path = os.path.join(os.path.dirname(__file__), 'data',
                                 'stochastic_gaussian_ranges.txt')
        self.interactor.load_ranges_from_files(
            {'stochastic_gaussian': file_path})
        child_int._view_items()
        self.assertEqual(child_int.input_f.distribution.mean, 39)
        self.assertEqual(child_int.input_f.distribution.std, 3)

    def test_save_project_ranges_for_stochastic_gaussian_interactor(self):
        """ Does saving parameters to file work for stochastic interactor
            with gaussian distribution ?
        """

        file_path = os.path.join(self.temp_dir,
                                 'test_save_ranges_for_stoch_gaussian.txt')
        child_int = self.interactor.interactor_stochastic_gaussian
        child_int._view_items()

        child_int.input_f.distribution.mean = 200
        child_int.input_f.distribution.std = 0.5
        self.interactor.save_ranges_to_files(
            {'stochastic_gaussian': file_path})

        # Read the saved file
        file_object = open(file_path, 'r')
        lines = file_object.readlines()
        lines = [line.split() for line in lines]
        file_object.close()
        os.remove(file_path)

        self.assertEqual(len(lines), 1)
        self.assertEqual(len(lines[0]), 3)
        self.assertEqual(lines[0][1], str(200.0))
        self.assertEqual(lines[0][2], str(0.5))

    def test_load_project_ranges_for_stochastic_triangular_interactor(self):
        """ Does loading parameters from file work for triangular interactor
            with triangular distribution ?
        """

        child_int = self.interactor.interactor_stochastic_triangular
        file_path = os.path.join(os.path.dirname(__file__), 'data',
                                 'stochastic_triangular_ranges.txt')
        self.interactor.load_ranges_from_files(
            {'stochastic_triangular': file_path})
        child_int._view_items()
        self.assertEqual(child_int.input_g.distribution.mode, 44)
        self.assertEqual(child_int.input_g.distribution.low, 39)
        self.assertEqual(child_int.input_g.distribution.high, 49)

    def test_save_project_ranges_for_stochastic_triangular_interactor(self):
        """ Does saving parameters to file work for stochastic interactor
            with triangular distribution ?
        """

        file_path = os.path.join(self.temp_dir,
                                 'test_save_ranges_for_stoch_triangular.txt')
        child_int = self.interactor.interactor_stochastic_triangular
        child_int._view_items()

        child_int.input_g.distribution.mode = 40.0
        child_int.input_g.distribution.low = 30.0
        child_int.input_g.distribution.high = 50.0
        self.interactor.save_ranges_to_files(
            {'stochastic_triangular': file_path})

        # Read the saved file
        file_object = open(file_path, 'r')
        lines = file_object.readlines()
        lines = [line.split() for line in lines]
        file_object.close()
        os.remove(file_path)

        self.assertEqual(len(lines), 1)
        self.assertEqual(len(lines[0]), 4)
        self.assertEqual(lines[0][1], str(40.0))
        self.assertEqual(lines[0][2], str(30.0))
        self.assertEqual(lines[0][3], str(50.0))

    def test_load_project_ranges_for_stochastic_uniform_interactor(self):
        """ Does loading parameters from file work for stochastic interactor
            with uniform distribution ?
        """

        child_int = self.interactor.interactor_stochastic_uniform
        file_path = os.path.join(os.path.dirname(__file__), 'data',
                                 'stochastic_uniform_ranges.txt')
        self.interactor.load_ranges_from_files(
            {'stochastic_uniform': file_path})
        child_int._view_items()
        self.assertEqual(child_int.input_h.distribution.low, 40)
        self.assertEqual(child_int.input_h.distribution.high, 58)

    def test_save_project_ranges_for_stochastic_uniform_interactor(self):
        """ Does saving parameters to file work for stochastic interactor
            with uniform distribution ?
        """

        file_path = os.path.join(self.temp_dir,
                                 'test_save_ranges_for_stoch_uniform.txt')
        child_int = self.interactor.interactor_stochastic_uniform
        child_int._view_items()

        child_int.input_h.distribution.low = 30.0
        child_int.input_h.distribution.high = 50.0
        self.interactor.save_ranges_to_files({'stochastic_uniform': file_path})

        # Read the saved file
        file_object = open(file_path, 'r')
        lines = file_object.readlines()
        lines = [line.split() for line in lines]
        file_object.close()
        os.remove(file_path)

        self.assertEqual(len(lines), 1)
        self.assertEqual(len(lines[0]), 3)
        self.assertEqual(lines[0][1], str(30.0))
        self.assertEqual(lines[0][2], str(50.0))

    def test_load_global_ranges_with_project_ranges(self):
        """ Do global ranges get overwritten by the project settings ?
        """

        code = "from blockcanvas.debug.my_operator import add,mul\n"\
               "d = mul(a, b)\n" \
               "e = mul(c, 3)\n" \
               "f = add(d,e)"
        self.block = Block(code)
        self.context['c'] = 2.0

        # This is to be done because the interactor doesn't get updated with
        # change in block.
        i_config = InteractorConfig(var_configs=[
            VariableConfig(name='a', type='Shadow'),
            VariableConfig(name='b', type='Parametric'),
            VariableConfig(name='c', type='Shadow'),
            VariableConfig(name='d', type='Parametric')
        ])
        self.interactor = ConfigurableInteractor(block=self.block,
                                                 context=self.context,
                                                 interactor_config=i_config)

        child_int = self.interactor.interactor_shadow
        global_file_path = os.path.join(os.path.dirname(__file__), 'data',
                                        'global_user_range.txt')
        project_file_path = os.path.join(os.path.dirname(__file__), 'data',
                                         'project_ranges.txt')

        self.interactor.load_ranges_from_files({'shadow': project_file_path},
                                               {'shadow': global_file_path})
        child_int._view_items()

        # Range of a is obtained from the project settings and not the
        # global preferences
        self.assertAlmostEqual(child_int.input_a__low, 3.4)
        self.assertAlmostEqual(child_int.input_a__high, 5.0)

        self.assertNotEqual(child_int.input_a__low, 0.15)
        self.assertNotEqual(child_int.input_a__high, 9.3)

        # Range of c is obtained from the global preferences
        self.assertAlmostEqual(child_int.input_c__low, 2.0)
        self.assertAlmostEqual(child_int.input_c__high, 7.0)

    def test_load_global_ranges_without_project_ranges(self):
        """ Do global ranges get used when there are no project settings ?
        """

        code = "from blockcanvas.debug.my_operator import add,mul\n"\
               "d = mul(a, b)\n" \
               "e = mul(c, 3)\n" \
               "f = add(d,e)"
        self.block = Block(code)
        self.context['c'] = 2.0

        # This is to be done because the interactor doesn't get updated with
        # change in block.
        i_config = InteractorConfig(var_configs=[
            VariableConfig(name='a', type='Shadow'),
            VariableConfig(name='b', type='Parametric'),
            VariableConfig(name='c', type='Shadow'),
            VariableConfig(name='d', type='Parametric')
        ])
        self.interactor = ConfigurableInteractor(block=self.block,
                                                 context=self.context,
                                                 interactor_config=i_config)

        child_int = self.interactor.interactor_shadow
        global_file_path = os.path.join(os.path.dirname(__file__), 'data',
                                        'global_user_range.txt')

        self.interactor.load_ranges_from_files({},
                                               {'shadow': global_file_path})
        child_int._view_items()

        # Range of a is obtained from the project settings and not the
        # global preferences
        self.assertAlmostEqual(child_int.input_a__low, 0.15)
        self.assertAlmostEqual(child_int.input_a__high, 9.3)

        # Range of c is obtained from the global preferences
        self.assertAlmostEqual(child_int.input_c__low, 2.0)
        self.assertAlmostEqual(child_int.input_c__high, 7.0)
Beispiel #19
0
           'from numpy import zeros\n'\
           'from codetools.contexts.with_mask import Mask\n'\
           'with Mask((depth < 4000.0) & (depth > 1000.0)):vp=1.5 ; vs=1.0'

##     # Expanded form of with statement taken from PEP 343. This is just for testing
##     code =   'from numpy import zeros\n'\
##              'array_len = depth.shape\n'\
##              'vp = zeros(array_len)\n'\
##              'vs = zeros(array_len)\n'\
##              'from codetools.contexts.with_mask import Mask\n'\
##              'mgr = Mask((depth < 4000.0) & (depth > 1000.0))\n'\
##              'exit_code = mgr.__exit__\n'\
##              'mgr.__enter__()\n'\
##              'exc = True\n'\
##              'try:\n'\
##              '    try:\n'\
##              '        vp = 1.0\n'\
##              '        vs = 1.5\n'\
##              '    except:\n'\
##              '        exc = False\n'\
##              'finally:\n'\
##              '    if exc:\n'\
##              '        exit_code(None, None, None)'

    b = Block(code)
    b.execute(context)
    print 'vp', context['vp']
    print 'vs', context['vs']

### EOF ------------------------------------------------------------------------
    def test_tracebacks(self):
        'Tracebacks have correct file names and line numbers'

        # If we want tracebacks to make sense, then the reported file names and
        # line numbers need to associate with the code being executed
        # regardless which block represents and executes the code.

        def test(tb, lineno, filename):
            self.assertEqual(tb.tb_lineno, lineno + 1)
            self.assertEqual(tb.tb_frame.f_code.co_filename, filename)

        def tracebacks():
            "A list of the current exception's traceback objects."
            tb = sys.exc_info()[2]
            l = [tb]
            while tb.tb_next is not None:
                tb = tb.tb_next
                l.append(tb)
            return l

        class File(StringIO, object):
            "Extend StringIO with a 'name' attribute."

            def __init__(self, name, *args, **kw):
                super(File, self).__init__(*args, **kw)
                self.name = name

        a = Block(File('foo/a.py', 'y = x'))
        try:
            a.execute({})
        except NameError as e:
            test(tracebacks()[-1], 1, 'foo/a.py')
        del a

        a = Block(File('foo/a.py', 'import sys\ny = x'))
        try:
            a.execute({})
        except NameError as e:
            test(tracebacks()[-1], 2, 'foo/a.py')
        #del a # (use below in 'Compose')

        b = Block(
            File('foo/b.py',
                 "import re\nl=re.findall('a(.*?)a', 'abacada')\nx = l[2]"))
        try:
            b.execute({})
        except IndexError as e:
            test(tracebacks()[-1], 3, 'foo/b.py')
        #del b # (use below in 'Compose')

        # Compose
        c = Block((a, b))
        try:
            c.execute({})
        except NameError as e:
            test(tracebacks()[-1], 2, 'foo/a.py')
        try:
            c.execute({'x': 0})
        except IndexError as e:
            test(tracebacks()[-1], 3, 'foo/b.py')
        del a, b, c

        # Restrict
        a = Block(File('foo/a.py', 'a = 0\nb = 1\nc = 2/a'))
        try:
            a.restrict(outputs='c').execute({})
        except ZeroDivisionError as e:
            test(tracebacks()[-1], 3, 'foo/a.py')
        del a

        # Throw out a sub-block
        a = Block(File('foo/a.py', 'a = 0\nb = 1\nc = 2/a'))
        a.sub_blocks.pop(1)
        try:
            a.execute({})
        except ZeroDivisionError as e:
            test(tracebacks()[-1], 3, 'foo/a.py')
        del a

        # Swap sub-blocks between blocks
        a = Block(File('foo/a.py', 'a = 0\nb = 1'))
        b = Block(File('foo/b.py', 'c = 2\nd = x'))
        a.sub_blocks = b.sub_blocks
        try:
            a.execute({})
        except NameError as e:
            test(tracebacks()[-1], 2, 'foo/b.py')
        a.sub_blocks = b.sub_blocks[:]
        try:
            a.execute({})
        except NameError as e:
            test(tracebacks()[-1], 2, 'foo/b.py')
        del a, b
#    from scimath.units.length import meter

    code = "from blockcanvas.debug.my_operator import add, mul\n" \
           "c = add(a,b)\n" \
           "d = mul(c, 2)\n" \
           "e = mul(c, 3)\n" \
           "f = add(d,e)"

    block=Block(code)

#    context = ParametricContext(GeoContext(), {})
#    context['a'] = UnitArray((1,2,3), units=meter)
#    context['b'] = UnitArray((2,3,4), units=meter)
#
#    interactor = ParametricInteractor(context=context, block = block)
#    interactor.configure_traits()

    # Context setup.
    context = MultiContext(DataContext(name='Data'),{})
    context['a'] = 1
    context['b'] = 2

    interactor = ParametricInteractor(context=context, block = block)
    interactor.configure_traits()

    for shadow in context.shadows:
        block.execute(shadow)
        print shadow['f'], 'Check with:', 5*(shadow['a']+shadow['b'])

### EOF ------------------------------------------------------------------------
Beispiel #22
0
    #    from scimath.units.length import meter

    code = "from blockcanvas.debug.my_operator import add, mul\n" \
           "c = add(a,b)\n" \
           "d = mul(c, 2)\n" \
           "e = mul(c, 3)\n" \
           "f = add(d,e)"

    block = Block(code)

    #    context = ParametricContext(GeoContext(), {})
    #    context['a'] = UnitArray((1,2,3), units=meter)
    #    context['b'] = UnitArray((2,3,4), units=meter)
    #
    #    interactor = ParametricInteractor(context=context, block = block)
    #    interactor.configure_traits()

    # Context setup.
    context = MultiContext(DataContext(name='Data'), {})
    context['a'] = 1
    context['b'] = 2

    interactor = ParametricInteractor(context=context, block=block)
    interactor.configure_traits()

    for shadow in context.shadows:
        block.execute(shadow)
        print shadow['f'], 'Check with:', 5 * (shadow['a'] + shadow['b'])

### EOF ------------------------------------------------------------------------
Beispiel #23
0
class ParametricInteractorTestCase(unittest.TestCase):
    """ Unit testing for ParametricInteractor
    """
    def setUp(self):
        code = "from blockcanvas.debug.my_operator import add, mul\n" \
               "c = add(a,b)\n" \
               "d = mul(c, 2)\n" \
               "e = mul(c, 3)\n" \
               "f = add(d,e)"

        self.block = Block(code)

        # Context setup.
        self.context = MultiContext(DataContext(name='Data'), {})
        self.context['a'] = 1
        self.context['b'] = 2

    def test_attributes(self):
        """ Test if creation of attributes is working correctly
        """
        interactor = ParametricInteractor(context=self.context,
                                          block=self.block)

        self.assertTrue(hasattr(interactor, interactor._input_prefix + "a"))
        self.assertTrue(hasattr(interactor, interactor._input_prefix + "b"))

        # Check if the parameter items were written correctly
        attribute_a = getattr(interactor, interactor._input_prefix + 'a')
        attribute_b = getattr(interactor, interactor._input_prefix + 'b')

        self.assertEqual(attribute_a.step, 0)
        self.assertEqual(attribute_a.low, 1)
        self.assertEqual(attribute_a.high, 1)

        self.assertEqual(attribute_b.step, 0)
        self.assertEqual(attribute_b.low, 2)
        self.assertEqual(attribute_b.high, 2)

        # Check if the inputs in the interactor are right
        self.assertEqual(interactor.inputs, list(self.block.inputs))

    def test_create_shadows(self):
        """ Test if creating shadows is working correctly
        """
        interactor = ParametricInteractor(context=self.context,
                                          block=self.block)

        # Change the parameters for the attributes
        attribute_a = getattr(interactor, interactor._input_prefix + 'a')
        attribute_b = getattr(interactor, interactor._input_prefix + 'b')

        attribute_a.high = 4
        attribute_a.step = 1

        attribute_b.high = 3
        attribute_b.step = 1

        # Create the shadows.
        interactor._update_contexts_button_changed()

        # Check if the shadows were created correctly.
        self.assertEqual(
            len(self.context.shadows),
            len(attribute_a.output_list) * len(attribute_b.output_list))

        # Check if the shadow context gives desired result.
        self.block.execute(self.context.shadows[-1])
        self.assertEqual(
            self.context.shadows[-1]['f'], 5 *
            (self.context.shadows[-1]['a'] + self.context.shadows[-1]['b']))
Beispiel #24
0
            a.execute({})
        except NameError, e:
            test(tracebacks()[-1], 1, 'foo/a.py')
        del a

        a = Block(File('foo/a.py', 'import sys\ny = x'))
        try:
            a.execute({})
        except NameError, e:
            test(tracebacks()[-1], 2, 'foo/a.py')
        #del a # (use below in 'Compose')

        b = Block(File('foo/b.py',
                "import re\nl=re.findall('a(.*?)a', 'abacada')\nx = l[2]"))
        try:
            b.execute({})
        except IndexError, e:
            test(tracebacks()[-1], 3, 'foo/b.py')
        #del b # (use below in 'Compose')

        # Compose
        c = Block((a,b))
        try:
            c.execute({})
        except NameError, e:
            test(tracebacks()[-1], 2, 'foo/a.py')
        try:
            c.execute({'x':0})
        except IndexError, e:
            test(tracebacks()[-1], 3, 'foo/b.py')
        del a,b,c